【问题标题】:Is there WebFilter fires after Controller in Spring WebFlux using Netty Server?在使用 Netty Server 的 Spring WebFlux 中的 Controller 之后是否会触发 WebFilter?
【发布时间】:2023-02-24 09:49:55
【问题描述】:

我正在寻找 Spring WebFlux 中的 servlet Filter 等价物。 WebFilter 似乎只在控制器之前触发而不是之后。例如,我可以添加一个 WebFilter 来在收到请求时做某事,但我找不到等效的“过滤器”来在发回响应时做某事。

你能有一个双向触发的“过滤器”吗?

【问题讨论】:

标签: spring spring-webflux netty servlet-filters


【解决方案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);
    }
}

参考:https://www.baeldung.com/spring-webflux-filters

【讨论】:

  • 是的,我知道它可以同时修改请求和响应,但问题是WebFilter#filter() 只发生在实际控制器之前,而不是之后。
  • webflux 则不然。无论如何,我不明白为什么这样的内部实现细节甚至很重要,因为这显然符合您的要求。
  • 如果在controller之后不触发,怎么按照controller设置的response body来做呢?
  • 在 Webflux 中,客户端和服务器之间只有一个流,数据双向流动。一旦我们读取请求或响应主体进行处理,输入流就会被消耗,因此控制器或客户端不会收到主体。因此,在 Webflux 中拦截请求或响应主体并非易事。查看stackoverflow.com/a/45280764/4571544stackoverflow.com/questions/61706948/… 了解更多信息。
【解决方案2】:

只需在webFilterChain.filter 调用后添加代码即可。

@Component
public class MyFilter implements WebFilter {

@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
  Mono<Void> result = chain.filter(exchange);
  return result.then(<do-whatever>);
}

【讨论】:

  • 哈哈,是的,这只是在其他过滤器之后运行代码,而不是在出站期间在控制器之后运行。
  • 不,它没有。控制器将在处理完所有过滤器后调用,然后返回。至少应该如此。
  • 根据定义WebFilter 在控制器之前执行。您可以查看像 HandlerResultHandler 这样的特殊 bean,或者考虑可以用来包装处理程序并实现自己的逻辑的 function WebFlux endpoints
  • >哈哈,是的,这只是在其他过滤器之后运行代码,而不是在出站期间在控制器之后运行代码根据你的语气,我们是否可以认为你确实已经测试和验证了它?
  • @BalusC 是的,确认了
【解决方案3】:

我认为您正在寻找的技巧是当您在过滤器方法中调用过滤器链时,您需要以下内容

@Override
public Mono<Void> filter(@NonNull final ServerWebExchange exchange, @NonNull final WebFilterChain chain) {
        final ServerHttpRequest request = exchange.getRequest();
        final String requestUrl = request.getURI().toString();
        
        // preRequest: - YOUR LOGIC

        return chain.filter(exchange).doFinally(signalType -> {
            /* This doFinally is included so the tests will pass */
            log.info("postHandle: Just like an interceptor");
        });
}

【讨论】:

    猜你喜欢
    • 2019-03-11
    • 2021-10-26
    • 2019-01-15
    • 2019-11-09
    • 2018-04-05
    • 2022-01-11
    • 1970-01-01
    • 2018-07-05
    • 2020-07-24
    相关资源
    最近更新 更多