Spring WebFlux如何仅执行选定WebFilters并进入处理器方法
解决Spring WebFlux按路径执行指定WebFilter后直达处理器的问题
你当前的问题是:自定义FilterChain执行完选定过滤器后,调用chain.filter(exchange)会触发剩余全局WebFilter执行;返回Mono.empty()则会终止整个请求流程,连后端处理器都无法执行。要实现的目标是:执行完指定过滤器后,跳过其余WebFilter,直接进入请求处理器。
下面提供几种可行的解决方案:
方案1:直接调用DispatcherHandler完成请求处理
Spring WebFlux的请求链最终由DispatcherHandler负责路由到处理器方法。我们可以在选定过滤器执行完毕后,直接获取该Bean并调用,跳过后续的WebFilter链。
修改你的自定义FilterChain的filter方法:
@NotNull @Override public Mono<Void> filter(@NotNull ServerWebExchange exchange) { if (index < selectedFilters.size()) { return selectedFilters.get(index++).filter(exchange, this) .doOnError(throwable -> { // 这里添加自定义错误处理逻辑 }) .onErrorResume(throwable -> Mono.empty()); } else { // 直接调用DispatcherHandler,跳过剩余过滤器 DispatcherHandler dispatcherHandler = applicationContext.getBean(DispatcherHandler.class); return dispatcherHandler.handle(exchange); } }
方案2:通过WebFilterRegistrationBean控制过滤器匹配路径
这是更简洁、符合Spring设计规范的方式——不需要自定义FilterChain,而是通过注册Bean为每个WebFilter指定匹配路径,由Spring自动控制过滤器的执行范围。
比如,为需要匹配/foo/bar路径的过滤器配置注册Bean:
@Bean public WebFilterRegistrationBean<ClientAuthorizationFilter> clientAuthorizationFilterRegistration(ClientAuthorizationFilter filter) { WebFilterRegistrationBean<ClientAuthorizationFilter> registration = new WebFilterRegistrationBean<>(filter); registration.addUrlPatterns("/foo/bar"); return registration; } @Bean public WebFilterRegistrationBean<UserAuthenticationFilter> userAuthenticationFilterRegistration(UserAuthenticationFilter filter) { WebFilterRegistrationBean<UserAuthenticationFilter> registration = new WebFilterRegistrationBean<>(filter); registration.addUrlPatterns("/foo/bar"); return registration; } // 其他需要匹配/foo/bar的过滤器同理配置
对于非API路径的过滤器(比如AuditFilter),可以配置排除指定路径:
@Bean public WebFilterRegistrationBean<AuditFilter> auditFilterRegistration(AuditFilter filter) { WebFilterRegistrationBean<AuditFilter> registration = new WebFilterRegistrationBean<>(filter); registration.addUrlPatterns("/**"); // 匹配所有路径 registration.excludeUrlPatterns("/foo/bar"); // 排除目标路径 return registration; }
方案3:在入口WebFilter中构建局部过滤器链
如果必须通过自定义逻辑筛选过滤器,可以在一个入口WebFilter中构建局部过滤器链,执行完毕后直接调用DispatcherHandler:
@Component public class PathBasedFilterSelector implements WebFilter { @Autowired private ApplicationContext applicationContext; @Autowired private DispatcherHandler dispatcherHandler; @Override public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) { List<WebFilter> selectedFilters = getSelectedFilters(exchange); // 构建并执行选定过滤器的局部链 return Flux.fromIterable(selectedFilters) .reduce(Mono.empty(), (prev, filter) -> prev.then(filter.filter(exchange, new WebFilterChain() { int currentIndex = 0; @Override public Mono<Void> filter(ServerWebExchange exchange) { if (currentIndex < selectedFilters.size()) { return selectedFilters.get(currentIndex++).filter(exchange, this); } return Mono.empty(); } }))) .then(dispatcherHandler.handle(exchange)); // 执行完后直接进入处理器 } private List<WebFilter> getSelectedFilters(ServerWebExchange exchange) { List<WebFilter> selectedFilters = new ArrayList<>(); if (exchange.getRequest().getPath().toString().equals("/foo/bar")) { selectedFilters.add(applicationContext.getBean(ClientAuthorizationFilter.class)); selectedFilters.add(applicationContext.getBean(UserAuthenticationFilter.class)); selectedFilters.add(applicationContext.getBean(DealsTriggerFulfilBannerRequestValidationFilter.class)); } else { // selectedFilters.add(applicationContext.getBean(AuditFilter.class)); } return selectedFilters; } }
推荐方案
优先选择方案2,它利用Spring原生的过滤器注册机制,无需自定义复杂的链逻辑,配置简单且维护成本低,完全符合Spring WebFlux的设计思路。
内容的提问来源于stack exchange,提问作者Gurucharan Sharma
相关产品推荐
相关产品推荐

