Spring WebFlux Filters
1. обзор
Использование фильтров широко распространено в веб-приложениях, поскольку они дают нам возможность изменить запрос или ответ без изменения наших конечных точек.
В этом кратком руководстве мы опишем возможные способы их реализации с помощью WebFlux Framework.
Поскольку мы не будем вдаваться в подробности о самом фреймворке WebFlux, вы можете проверитьthis article для более подробной информации.
2. Maven Dependency
Прежде всего, давайте объявим зависимость WebFlux Maven:
org.springframework.boot
spring-boot-starter-webflux
3. Endpoints
Сначала нужно создать несколько конечных точек. Один для каждого метода: на основе аннотаций и на основе функций.
Начнем с контроллера на основе аннотаций:
@GetMapping(path = "/users/{name}")
public Mono getName(@PathVariable String name) {
return Mono.just(name);
}
Для функциональной конечной точки мы должны сначала создать обработчик:
@Component
public class PlayerHandler {
public Mono getName(ServerRequest request) {
Mono name = Mono.just(request.pathVariable("name"));
return ok().body(name, String.class);
}
}
А также отображение конфигурации маршрутизатора:
@Bean
public RouterFunction route(PlayerHandler playerHandler) {
return RouterFunctions
.route(GET("/players/{name}"), playerHandler::getName)
.filter(new ExampleHandlerFilterFunction());
}
4. Типы фильтров WebFlux
Инфраструктура WebFlux предоставляет два типа фильтров:WebFilters иHandlerFilterFunctions.
Основное различие между ними в том, чтоWebFilter implementations work for all endpoints и HandlerFilterFunction implementations will only work for Router-based ones.
4.1. WebFilterс
Мы реализуемWebFilter, чтобы добавить новый заголовок в ответ. В результате все ответы должны иметь такое поведение:
@Component
public class ExampleWebFilter implements WebFilter {
@Override
public Mono filter(ServerWebExchange serverWebExchange,
WebFilterChain webFilterChain) {
serverWebExchange.getResponse()
.getHeaders().add("web-filter", "web-filter-test");
return webFilterChain.filter(serverWebExchange);
}
}
4.2. HandlerFilterFunctionс
Для этого мы реализуем логику, которая устанавливает статус HTTP наFORBIDDEN, когда параметр «name» равен «test».
public class ExampleHandlerFilterFunction
implements HandlerFilterFunction {
@Override
public Mono filter(ServerRequest serverRequest,
HandlerFunction handlerFunction) {
if (serverRequest.pathVariable("name").equalsIgnoreCase("test")) {
return ServerResponse.status(FORBIDDEN).build();
}
return handlerFunction.handle(serverRequest);
}
}
5. тестирование
В WebFlux Framework есть простой способ протестировать наши фильтры:WebTestClient. Это позволяет нам проверять HTTP-вызовы к нашим конечным точкам.
Вот примеры конечной точки на основе аннотации:
@Test
public void whenUserNameIsexample_thenWebFilterIsApplied() {
EntityExchangeResult result = webTestClient.get()
.uri("/users/example")
.exchange()
.expectStatus().isOk()
.expectBody(String.class)
.returnResult();
assertEquals(result.getResponseBody(), "example");
assertEquals(
result.getResponseHeaders().getFirst("web-filter"),
"web-filter-test");
}
@Test
public void whenUserNameIsTest_thenHandlerFilterFunctionIsNotApplied() {
webTestClient.get().uri("/users/test")
.exchange()
.expectStatus().isOk();
}
И для функциональной конечной точки:
@Test
public void whenPlayerNameIsexample_thenWebFilterIsApplied() {
EntityExchangeResult result = webTestClient.get()
.uri("/players/example")
.exchange()
.expectStatus().isOk()
.expectBody(String.class)
.returnResult();
assertEquals(result.getResponseBody(), "example");
assertEquals(
result.getResponseHeaders().getFirst("web-filter"),
"web-filter-test");
}
@Test
public void whenPlayerNameIsTest_thenHandlerFilterFunctionIsApplied() {
webTestClient.get().uri("/players/test")
.exchange()
.expectStatus().isForbidden();
}
6. Заключение
В этом руководстве мы рассмотрели оба типа фильтров WebFlux и рассмотрели несколько примеров кода.
Для получения дополнительной информации о WebFlux Framework взгляните наdocumentation.
Как всегда, полный исходный код примеров можно найти вover on GitHub.