Step-by-Step Implementation of Spring WebFlux Filters
Below are the steps to implement Spring Webflux Filters.
Step 1: Add Maven Dependency
First, let us define the Maven dependency for WebFlux:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
Step 2: Create an Endpoint
We need to construct a few endpoints. Annotation-based and functional-based methods, one for each. The annotation-based controller will be discussed first:
// Define a Spring WebFlux controller endpoint for handling GET requests with a path variable
@GetMapping(path = "/authors/{name}")
// Method to retrieve and return a Mono<String> representing the provided path variable "name"
public Mono<String> getName(@PathVariable String name) {
// Return a Mono<String> containing the value of the provided path variable "name"
return Mono.just(name);
}
Step 3: Create functional Endpoint
We must construct a handler for the functional endpoint:
Java
// Spring component class representing a handler for author-related operations @Component public class AuthorHandler { // Method to handle retrieving and returning a author name based on the provided ServerRequest public Mono<ServerResponse> getName(ServerRequest request) { // Extract the "name" path variable from the ServerRequest and wrap it in a Mono Mono<String> name = Mono.just(request.pathVariable( "name" )); // Return a ServerResponse with an OK status and the author name in the response body return ServerResponse.ok().body(name, String. class ); } } |
Step 4: WebFlux Routing Function
To achieve the same endpoint, using the Functional Web Framework, we can build a Functional Router. The Routing Function that we are developing here has a Handler Function attached to it.
Java
// Define a RouterFunction bean for handling GET requests to "/authors/{id}" @Bean public RouterFunction<ServerResponse> getAuthorRoute() { return route(GET( "/authors/{id}" ), // Lambda expression handling the request and returning a ServerResponse request -> ok().body(service .getAuthor(request.pathVariable( "id" )), Author. class ) ); } |
Step 5: Add a new header to the response
Apply a WebFilter to the response in order to append a new header. This means that every response behaves like this:
Java
// Spring component class implementing the WebFilter interface for filtering web requests and responses @Component public class SecondWebFilter implements WebFilter { // Method to perform filtering on the ServerWebExchange and WebFilterChain @Override public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) { // Add a custom header to the response indicating the use of this web filter serverWebExchange.getResponse().getHeaders().add( "web-filter" , "web-filter-test" ); // Continue the filter chain, allowing the request to proceed to the next filters or handlers return webFilterChain.filter(serverWebExchange); } } |
Step 6: Create HandlerFilterFunction
Create a logic that, in the event that the “name” argument equals “article” sets the HTTP status to OK.
Java
// Class implementing HandlerFilterFunction for filtering handler functions in a reactive web application public class SecondHandlerFilterFunction implements HandlerFilterFunction<ServerResponse, ServerResponse> { // Method to perform filtering on the ServerRequest and HandlerFunction @Override public Mono<ServerResponse> filter(ServerRequest serverRequest, HandlerFunction<ServerResponse> handlerFunction) { // Check if the "name" path variable is "article"; if true, return a OK response if (serverRequest.pathVariable( "name" ).equalsIgnoreCase( "article" )) { return ServerResponse.status(HttpStatus.OK).build(); } // Continue with the original handler function if the condition is not met return handlerFunction.handle(serverRequest); } } |
- In this case, we built up a mechanism to set the HTTP status to OK if the value of the “name” field is “article”.
- It is possible to filter handler functions in a reactive web application by using the ExampleHandlerFilterFunction class, which implements HandlerFilterFunction.
- If “article” is present in the “name” path variable, the filter method verifies it and provides a 200 status code along with a Ok response.
- The purpose of this filter is to intercept and alter the response prior to it reaching the handler function, based on predetermined criteria.
Step 7: Test the WebTestClient
The WebTestClient in the WebFlux Framework provides a simple method for testing our filters. We can test HTTP requests to our endpoints with it.
Annotation-based endpoint:
Java
// Test case to verify that the web filter is applied when the username is "w3wiki" @Test public void whenUserNameIsw3wiki_thenWebFilterIsApplied() { // Perform a GET request to "/users/w3wiki" using the WebTestClient EntityExchangeResult<String> result = webTestClient.get() .uri( "/users/w3wiki" ) .exchange() // Expect a successful response with status code 200 (OK) .expectStatus().isOk() // Expect the response body to be of type String .expectBody(String. class ) .returnResult(); // Assert that the response body matches the expected username "w3wiki" assertEquals(result.getResponseBody(), "w3wiki" ); // Assert that the "web-filter" header is present in the response and has the expected value assertEquals(result.getResponseHeaders().getFirst( "web-filter" ), "web-filter-test" ); } // Test case to verify that the HandlerFilterFunction is not applied when the username is "article" @Test public void whenUserNameIsTest_thenHandlerFilterFunctionIsNotApplied() { // Perform a GET request to "/users/article" using the WebTestClient webTestClient.get().uri( "/users/article" ) .exchange() // Expect a successful response with status code 200 (OK) .expectStatus().isOk(); } |
Functional endpoint:
Java
// Test case to verify that the web filter is applied when the author name is "w3wiki" @Test public void whenAuthorNameIsw3wiki_thenWebFilterIsApplied() { // Perform a GET request to "/authors/w3wiki" using the WebTestClient EntityExchangeResult<String> result = webTestClient.get() .uri( "/authors/w3wiki" ) .exchange() // Expect a successful response with status code 200 (OK) .expectStatus().isOk() // Expect the response body to be of type String .expectBody(String. class ) .returnResult(); // Assert that the response body matches the expected author name "w3wiki" assertEquals(result.getResponseBody(), "w3wiki" ); // Assert that the "web-filter" header is present in the response and has the expected value assertEquals(result.getResponseHeaders().getFirst( "web-filter" ), "web-filter-test" ); } // Test case to verify that the HandlerFilterFunction is applied when the author name is "article" @Test public void whenAuthorNameIsTest_thenHandlerFilterFunctionIsApplied() { // Perform a GET request to "/authors/article" using the WebTestClient webTestClient.get().uri( "/authors/article" ) .exchange() // Expect a Ok response status code (200) .expectStatus().isOk(); } |
Spring WebFlux Filters helps guarantee that response material is always consumed and offers a mechanism for encoding to and from higher level objects. The filter method allows us to interface with web requests and perform operations via a ServerWebExchange.
Spring WebFlux Filters
In Spring WebFlux, the filters are used to do modifications like it modifies the requests and responses going through the server. This Filter allows us to do basic tasks like modifying headers, logging, authentication etc. In Spring WebFlux Filters, filters are created using WebFilter interface and @WebFilter annotation.
Implementation of WebFlux Filters
public interface WebFilter {
Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain);
}
Contact Us