你可以通过使用路由函数生成器上的前、后或过滤方法来过滤处理函数。通过注解,你可以通过使用 @ControllerAdviceServletFilter或两者实现类似的功能。该过滤器将应用于由构建器构建的所有路由。这意味着在嵌套路由中定义的过滤器并不适用于 「顶层」路由。例如,考虑下面的例子:

    1. RouterFunction<ServerResponse> route = route()
    2. .path("/person", b1 -> b1
    3. .nest(accept(APPLICATION_JSON), b2 -> b2
    4. .GET("/{id}", handler::getPerson)
    5. .GET(handler::listPeople)
    6. // 添加自定义请求头的 before 过滤器只适用于两个 GET 路由。
    7. .before(request -> ServerRequest.from(request)
    8. .header("X-RequestHeader", "Value")
    9. .build()))
    10. .POST("/person", handler::createPerson))
    11. // 记录响应的后置过滤器适用于所有路由,包括嵌套的路由。
    12. .after((request, response) -> logResponse(response))
    13. .build();

    路由器构建器上的过滤方法接收一个 HandlerFilterFunction:一个接收 ServerRequest 和 HandlerFunction 并返回 ServerResponse 的函数。处理程序函数参数代表链中的下一个元素。这通常是被路由到的处理程序,但如果应用多个过滤器,它也可以是另一个过滤器。

    现在我们可以给我们的路由添加一个简单的安全过滤器,假设我们有一个 SecurityManager,可以确定某个特定路径是否被允许。下面的例子显示了如何做到这一点:

    1. SecurityManager securityManager = ...
    2. RouterFunction<ServerResponse> route = route()
    3. .path("/person", b1 -> b1
    4. .nest(accept(APPLICATION_JSON), b2 -> b2
    5. .GET("/{id}", handler::getPerson)
    6. .GET(handler::listPeople))
    7. .POST("/person", handler::createPerson))
    8. .filter((request, next) -> {
    9. if (securityManager.allowAccessTo(request.path())) {
    10. return next.handle(request);
    11. }
    12. else {
    13. return ServerResponse.status(UNAUTHORIZED).build();
    14. }
    15. })
    16. .build();

    前面的例子表明,调用 next.handle(ServerRequest) 是可选的。我们只在允许访问时让处理函数运行。

    除了在路由器函数生成器上使用过滤器方法,还可以通过 RouterFunction.filter(HandlerFilterFunction)将过滤器应用于现有的路由器函数。

    :::info 对功能端点的 CORS 支持是通过一个专门的 CorsFilter 提供的(原文的跳转链接失效了,所以不太确定是如何配置的,难道是和 SpringMVC 提供的是同一个?因为 WebMvc.fn 也运行在 DispatcherServlet 上)。 :::