Spring WebFlux Filters – Spring WebFlux过滤器

最后修改: 2018年 4月 25日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

The use of filters is widespread in web applications since they give us a way to modify a request or response without changing our endpoints.

过滤器的使用在网络应用中很普遍,因为它们给我们提供了一种修改请求或响应的方法,而无需改变我们的端点。

In this quick tutorial, we’ll describe possible ways of implementing them with the WebFlux Framework.

在这个快速教程中,我们将描述用WebFlux框架实现它们的可能方法。

As we won’t go into details about the WebFlux framework itself, you might want to check out this article for more details.

由于我们不会对WebFlux框架本身进行详细介绍,您可能想查看这篇文章以了解更多细节。

2. Maven Dependency

2.Maven的依赖性

First of all, let’s declare the WebFlux Maven dependency:

首先,让我们声明WebFlux的Maven依赖性。

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

3. Endpoints

3.端点

We have to create some endpoints first. One for each method: annotation-based and functional-based.

我们必须首先创建一些端点。每种方法都有一个:基于注释的和基于功能的。

Let’s start with the annotation-based controller:

让我们从基于注释的控制器开始。

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

For the functional endpoint we have to create a handler first:

对于功能端点,我们必须首先创建一个处理程序。

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

And also a router configuration mapping:

还有一个路由器配置映射。

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

4. Types of WebFlux Filters

4.WebFlux过滤器的类型

The WebFlux framework provides two types of filters: WebFilters and HandlerFilterFunctions.

WebFlux框架提供了两种类型的过滤器。WebFiltersHandlerFilterFunctions

The main difference between them is that WebFilter implementations work for all endpoints and HandlerFilterFunction implementations will only work for Router-based ones.

它们之间的主要区别是:WebFilter实现对所有端点都有效HandlerFilterFunction实现只对基于Router的端点有效。

4.1. WebFilter

4.1WebFilter

We’ll implement a WebFilter to add a new header to the response. As a result, all responses should have this behavior:

我们将实现一个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

4.2.HandlerFilterFunction[/em]

For this one, we implement a logic that sets the HTTP status to FORBIDDEN when the “name” parameter is equal to “test”.

对于这个,我们实现了一个逻辑,当 “name “参数等于 “test “时,将HTTP状态设置为FORBIDDEN

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. Testing

5.测试

In WebFlux Framework there’s an easy way to test our filters: the WebTestClient. It allows us to test HTTP calls to our endpoints.

在WebFlux框架中,有一个简单的方法来测试我们的过滤器:WebTestClient。它允许我们测试对我们端点的HTTP调用。

Here are examples of the annotation-based endpoint:

下面是基于注释的终端的例子。

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

    assertEquals(result.getResponseBody(), "baeldung");
    assertEquals(
      result.getResponseHeaders().getFirst("web-filter"), 
      "web-filter-test");
}

@Test
public void whenUserNameIsTest_thenHandlerFilterFunctionIsNotApplied() {
    webTestClient.get().uri("/users/test")
      .exchange()
      .expectStatus().isOk();
}

And for the functional endpoint:

而对于功能端点。

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

    assertEquals(result.getResponseBody(), "baeldung");
    assertEquals(
      result.getResponseHeaders().getFirst("web-filter"),
      "web-filter-test");
} 

@Test 
public void whenPlayerNameIsTest_thenHandlerFilterFunctionIsApplied() {
    webTestClient.get().uri("/players/test")
      .exchange()
      .expectStatus().isForbidden(); 
}

6. Conclusion

6.结语

We’ve covered both types WebFlux filters in this tutorial and had a look at some code examples.

我们在本教程中已经介绍了这两种类型的WebFlux过滤器,并看了一些代码示例。

For more information about the WebFlux Framework, have a look at the documentation.

有关WebFlux框架的更多信息,请查看文档

As always, the full source code for the examples can be found over on GitHub.

一如既往,可以在GitHub上找到这些例子的完整源代码