Перейти к основному содержимому

Весенние фильтры WebFlux

· 3 мин. чтения

Задача: Сумма двух чисел

Напишите функцию twoSum. Которая получает массив целых чисел nums и целую сумму target, а возвращает индексы двух чисел, сумма которых равна target. Любой набор входных данных имеет ровно одно решение, и вы не можете использовать один и тот же элемент дважды. Ответ можно возвращать в любом порядке...

ANDROMEDA

1. Обзор

Использование фильтров широко распространено в веб-приложениях, поскольку они дают нам возможность изменять запрос или ответ без изменения наших конечных точек.

В этом кратком руководстве мы опишем возможные способы их реализации с помощью WebFlux Framework.

Поскольку мы не будем вдаваться в подробности о самой структуре WebFlux, вы можете прочитать эту статью для получения более подробной информации.

2. Зависимость от Maven

Прежде всего, давайте объявим зависимость WebFlux Maven:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

3. Конечные точки

Сначала мы должны создать несколько конечных точек. По одному для каждого метода: на основе аннотаций и на основе функций.

Начнем с контроллера на основе аннотаций:

@GetMapping(path = "/users/{name}")
public Mono<String> getName(@PathVariable String name) {
return Mono.just(name);
}

Для функциональной конечной точки мы должны сначала создать обработчик:

@Component
public class PlayerHandler {
public Mono<ServerResponse> getName(ServerRequest request) {
Mono<String> name = Mono.just(request.pathVariable("name"));
return ok().body(name, String.class);
}
}

А также сопоставление конфигурации маршрутизатора:

@Bean
public RouterFunction<ServerResponse> route(PlayerHandler playerHandler) {
return RouterFunctions
.route(GET("/players/{name}"), playerHandler::getName)
.filter(new ExampleHandlerFilterFunction());
}

4. Типы фильтров WebFlux

Платформа WebFlux предоставляет два типа фильтров: WebFilter s и HandlerFilterFunctions .

Основное различие между ними заключается в том, что реализации WebFilter работают для всех конечных точек , а реализации HandlerFilterFunction будут работать только для тех, которые основаны на Router . ``

4.1. Веб-фильтр

Мы реализуем WebFilter , чтобы добавить в ответ новый заголовок. В результате все ответы должны иметь такое поведение:

@Component
public class ExampleWebFilter implements WebFilter {

@Override
public Mono<Void> filter(ServerWebExchange serverWebExchange,
WebFilterChain webFilterChain) {

serverWebExchange.getResponse()
.getHeaders().add("web-filter", "web-filter-test");
return webFilterChain.filter(serverWebExchange);
}
}

4.2. HandlerFilterFunction

Для этого мы реализуем логику, которая устанавливает статус HTTP в ЗАПРЕЩЕНО , когда параметр «имя» равен «тест».

public class ExampleHandlerFilterFunction 
implements HandlerFilterFunction<ServerResponse, ServerResponse> {

@Override
public Mono<ServerResponse> filter(ServerRequest serverRequest,
HandlerFunction<ServerResponse> handlerFunction) {
if (serverRequest.pathVariable("name").equalsIgnoreCase("test")) {
return ServerResponse.status(FORBIDDEN).build();
}
return handlerFunction.handle(serverRequest);
}
}

5. Тестирование

В WebFlux Framework есть простой способ протестировать наши фильтры: WebTestClient . Это позволяет нам тестировать HTTP-вызовы к нашим конечным точкам.

Вот примеры конечной точки на основе аннотаций:

@Test
public void whenUserNameIsForEach_thenWebFilterIsApplied() {
EntityExchangeResult<String> result = webTestClient.get()
.uri("/users/foreach")
.exchange()
.expectStatus().isOk()
.expectBody(String.class)
.returnResult();

assertEquals(result.getResponseBody(), "foreach");
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 whenPlayerNameIsForEach_thenWebFilterIsApplied() {
EntityExchangeResult<String> result = webTestClient.get()
.uri("/players/foreach")
.exchange()
.expectStatus().isOk()
.expectBody(String.class)
.returnResult();

assertEquals(result.getResponseBody(), "foreach");
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 ознакомьтесь с документацией .

Как всегда, полный исходный код примеров можно найти на GitHub .