如何使 WebFilter 在非 WebFlux/非反应式 Spring Boot 应用程序中工作?

Posted

技术标签:

【中文标题】如何使 WebFilter 在非 WebFlux/非反应式 Spring Boot 应用程序中工作?【英文标题】:How to make WebFilter work in a non-WebFlux/non-reactive Spring Boot application? 【发布时间】:2020-12-23 14:59:32 【问题描述】:

我正在尝试解决这个问题:How to rewrite URLs with Spring (Boot) via REST Controllers? 通过创建某种“过滤器”,该过滤器将应用于每个传入的 HTTP 请求。

这个问题的一些答案涵盖了这个问题:Spring Boot Adding Http Request Interceptors 但是接口HandlerInterceptor 处理javax'HttpServletRequestHttpServletResponse,它们不如Spring 引入的新类,即ServerWebExchange(参见下面代码中setLocation() 的使用)实用,它出现在名字听起来很有希望的界面,org.springframework.web.server.WebFilter:

所以我以这样的方式结束:

@Component
public class LegacyRestRedirectWebFilter implements WebFilter 

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) 
        URI origin = exchange.getRequest().getURI();
        String path = origin.getPath();
        if (path.startsWith("/api/")) 
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.MOVED_PERMANENTLY);
            URI location = UriComponentsBuilder.fromUri(origin).replacePath(path.replaceFirst("/api/", "/rest/")).build().toUri();
            response.getHeaders().setLocation(location);
        
        return chain.filter(exchange);
    


...以同样的方式人们正在做类似的事情:

Spring WebFlux add WebFIlter to match specific paths WebFilter in WebFlux application

唉,我的过滤器永远不会被调用!!!

问题是:我不在“WebFlux”上下文中(与上述问题相反),因为:

    我不需要,而且 我尝试了以下问题:

Reactive Webfilter is not working when we have spring-boot-starter-web dependency in classpath(但没有明确的答案);标记重复: Don't spring-boot-starter-web and spring-boot-starter-webflux work together?

Spring WebFlux with traditional Web Security(我的pom.xml 中有一个“传统”spring-boot-starter-security 依赖项加上一个扩展WebSecurityConfigurerAdapter@Configuration 类 - 但不愿意将其迁移到...顺便说一句?)

我也不明白为什么我需要在 WebFlux 上下文中,因为 org.springframework.web.server.WebFilter 既不处理 reactive 也不处理 Webflux,对吧? ..或者是吗?这在 Javadoc 中不是很清楚。

【问题讨论】:

您的应用程序要么是 Web 应用程序,要么是 webflux 应用程序。不能两者兼有,webfilter 是 webflux 的一部分,因此如果您的应用程序是 webflux 应用程序,它将被加载和使用。如果您的类路径中同时具有 web 和 webflux,则默认情况下,spring boot 将作为 Web 应用程序启动,并且您应该使用 Filter baeldung.com/spring-boot-add-filter 而无需查看您的 pom.xml/gradle,它很难知道您拥有哪种类型的应用程序。 WebFilter 位于spring-web-5.1.9.RELEASE.jar,如何成为“WebFlux”的一部分?! 顺便说一句,当您在我的另一个问题上请求 pom.xml 时,我将其发布在这里:***.com/questions/63737318/… ...也感谢您将我指向这个(简单)Filter,但经过快速搜索(尽管 Baeldung 没有指定它是哪个过滤器...)我发现这是@ 987654347@,正如我上面所说,我会尽量避免使用它,因为它是纯“javax”代码,它处理 (Http)ServletRequest/(Http)ServletResponse,[参见 RequestResponseLoggingFilter 中的转换]。跨度> 好吧,因为我还没有看到你的 pom.xml(直到现在),许多人将 webflux 添加到他们的 spring-web 应用程序中以仅使用 WebClient。因此默认情况下,另一方面,您希望使用WebFilter,因为您想构建一个 webflux 应用程序。而你的问题是你正在引入不支持 webflux (springfox v2.9.2) 的东西,所以 springfox 可能会强制你的应用程序作为 web 应用程序启动。 【参考方案1】:

事实上,我没有找到让WebFilter 在非WebFlux 上下文中工作的方法,但我可以成功实现这样的过滤器,它既实现了javax.servlet.Filter(非反应式)又实现了org.springframework.web.server.WebFilter (反应性)。

这是我对另一个相关问题的回答:https://***.com/a/63780659/666414

【讨论】:

以上是关于如何使 WebFilter 在非 WebFlux/非反应式 Spring Boot 应用程序中工作?的主要内容,如果未能解决你的问题,请参考以下文章

Spring WebFlux添加WebFIlter以匹配特定路径

将 WebFilter Spring WebFlux 添加到路径

(WebFlux)004WebFilter踩坑记录

(WebFlux)004WebFilter踩坑记录

(WebFlux)004WebFilter踩坑记录

为啥在 webflux 中使用 WebFilter corsFilter 时请求返回 404 状态?