如何让Api-Gateway的CustomGlobalFilter过滤网关自身Controller请求?
问题根源
Spring Cloud Gateway 的 GlobalFilter 仅作用于网关路由转发的请求,而网关自身的 @Controller/@RestController 请求是由 Spring MVC/WebFlux 的核心调度器直接处理,不会进入 Gateway 的过滤链路,因此调整 @Order 或添加路由配置无法覆盖这类请求。
解决方案
方案1:将网关自身接口配置为路由转发到自身
把网关作为服务注册到注册中心,然后添加路由规则,让前端请求网关自身接口时走 Gateway 过滤链。
示例配置(application.yml):
spring: cloud: gateway: routes: # 原有业务服务路由 - id: other-service-route uri: lb://other-service predicates: - Path=/api/service/** # 网关自身接口的路由(指向网关服务名) - id: gateway-self-route uri: lb://api-gateway-service # 替换为你的网关服务注册名 predicates: - Path=/api/gateway/** # 网关自身Controller的接口路径
此方案下,所有请求(包括网关自身接口)都会经过 GlobalFilter 处理,但需要确保网关已注册到服务发现组件(如Nacos/Eureka)。
方案2:复用过滤逻辑,分别实现 Gateway Filter 和 MVC/WebFlux 拦截器
将核心过滤逻辑抽离为公共类,同时适配 Gateway 的 GlobalFilter 和网关自身Controller的拦截器(MVC用HandlerInterceptor,WebFlux用WebFilter)。
步骤1:抽离公共过滤逻辑
@Component public class CommonFilterHandler { /** * 公共过滤逻辑:返回true表示通过,false表示拦截 */ public boolean processFilter(HttpServletRequest request, HttpServletResponse response) { // 示例:校验请求头Token String token = request.getHeader("Authorization"); if (token == null || !token.startsWith("Bearer ")) { response.setStatus(HttpStatus.UNAUTHORIZED.value()); return false; } // 其他过滤逻辑:日志、参数校验等 return true; } }
步骤2:实现 Gateway GlobalFilter
@Component public class CustomGlobalFilter implements GlobalFilter, Ordered { @Autowired private CommonFilterHandler commonFilterHandler; @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { HttpServletRequest request = exchange.getRequest().getNativeRequest(HttpServletRequest.class); HttpServletResponse response = exchange.getResponse().getNativeResponse(HttpServletResponse.class); boolean pass = commonFilterHandler.processFilter(request, response); if (!pass) { exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } return chain.filter(exchange); } @Override public int getOrder() { return -100; // 调整顺序,确保在核心过滤逻辑前执行 } }
步骤3:适配网关自身Controller的拦截器
如果网关用的是Spring MVC:
// 1. 实现HandlerInterceptor @Component public class CustomMvcInterceptor implements HandlerInterceptor { @Autowired private CommonFilterHandler commonFilterHandler; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { return commonFilterHandler.processFilter(request, response); } } // 2. 注册拦截器 @Configuration public class MvcInterceptorConfig implements WebMvcConfigurer { @Autowired private CustomMvcInterceptor customMvcInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(customMvcInterceptor) .addPathPatterns("/api/gateway/**"); // 网关自身接口路径 } }
如果网关用的是Spring WebFlux(Gateway默认依赖WebFlux):
@Component public class CustomWebFilter implements WebFilter, Ordered { @Autowired private CommonFilterHandler commonFilterHandler; @Override public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) { HttpServletRequest request = exchange.getRequest().getNativeRequest(HttpServletRequest.class); HttpServletResponse response = exchange.getResponse().getNativeResponse(HttpServletResponse.class); boolean pass = commonFilterHandler.processFilter(request, response); if (!pass) { exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } return chain.filter(exchange); } @Override public int getOrder() { return -100; // 调整优先级 } }
此方案无需修改请求路径,同时覆盖路由转发和网关自身接口的过滤需求。
方案3:使用WebFilter统一处理(仅适用于WebFlux网关)
如果网关基于WebFlux(Spring Cloud Gateway默认如此),直接实现 WebFilter 即可覆盖所有WebFlux处理的请求,包括路由转发和网关自身Controller的请求,无需额外配置 GlobalFilter。
示例代码:
@Component public class UnifiedWebFilter implements WebFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) { // 过滤逻辑示例:记录请求日志 String path = exchange.getRequest().getPath().toString(); System.out.println("Received request: " + path); // 其他逻辑:鉴权、参数校验等 return chain.filter(exchange); } @Override public int getOrder() { return -100; // 确保优先级高于默认过滤器 } }
内容的提问来源于stack exchange,提问作者vikiJ
相关产品推荐
相关产品推荐

