Spring Cloud Gateway 自定义过滤器
发布时间:2026/8/15 22:46:16 作者:尧图编辑部 阅读量:1,286

文章目录Spring Cloud Gateway 自定义过滤器一、依赖版本二、两种自定义过滤器三、Pre 与 Post四、执行顺序五、自定义 GatewayFilter普通5.1 实现类5.2 yml 配置5.3 带参过滤器 shortcut 写法可选六、自定义 GlobalFilter全局6.1 常用 GlobalFilter 场景七、普通 vs 全局 对照示例八、完整接入步骤8.1 创建 Filter 类8.2 配置 GatewayFilter可选8.3 启动验证九、GatewayFilter 与 GlobalFilter 选型十、常见问题10.1 yml 配了 Custom 但报 Unknown filter10.2 GlobalFilter 不生效10.3 Pre 里如何中断请求10.4 Boot 4 配置不生效十一、总结Spring Cloud Gateway 自定义过滤器基于spring-cloud-demo· Spring Boot 4.1.0 Spring Cloud 2025.1.2一、依赖版本组件版本Java21Spring Boot4.1.0Spring Cloud2025.1.2Gateway 依赖spring-cloud-starter-gateway-server-webfluxBoot 4 配置前缀为spring.cloud.gateway.server.webflux.*非 Boot 3 的spring.cloud.gateway.*。二、两种自定义过滤器Gateway 内置大量 FilterAddRequestHeader、StripPrefix 等。业务需要鉴权、日志、灰度等逻辑时需自定义 Filter。对比项GatewayFilter普通GlobalFilter全局作用范围指定路由或 default-filters 全部路由所有路由实现方式继承AbstractGatewayFilterFactory实现GlobalFilterOrderedyml 配置需要filters:或default-filters:不需要注册为 Bean 即生效典型场景某条路由加参数、单路由鉴权全局日志、全站鉴权、TraceId配置写法filters: - name: Customargs无三、Pre 与 Post无论普通还是全局一次 Filter 可同时包含Pre和Post阶段时机示例Pre请求转发到后端之前鉴权、加 Header、限流Post后端响应返回客户端之前改响应头、记录耗时returnchain.filter(exchange).then(Mono.fromRunnable(()-{// Postchain.filter 之后执行}));// Prereturn 之前的代码四、执行顺序所有 Filter 合并为一条链按order 值排序order越小越先执行order相同时defaultFilterGatewayFilterGlobalFilter实现Ordered接口或加Order注解指定 order。Ordered.LOWEST_PRECEDENCE表示优先级最低最后执行。流程图见doc/gateway-diagrams.drawio→ 页「过滤器执行顺序」五、自定义 GatewayFilter普通5.1 实现类继承AbstractGatewayFilterFactoryConfig类名必须以GatewayFilterFactory结尾。yml 中的name取类名前缀CustomGatewayFilterFactory→name: Custompackagecom.emrys.gateway.filter;importlombok.Data;importlombok.extern.slf4j.Slf4j;importorg.springframework.cloud.gateway.filter.GatewayFilter;importorg.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;importorg.springframework.core.Ordered;importorg.springframework.stereotype.Component;importreactor.core.publisher.Mono;Slf4jComponent// 必须交给 Spring 管理publicclassCustomGatewayFilterFactoryextendsAbstractGatewayFilterFactoryCustomGatewayFilterFactory.ConfigimplementsOrdered{publicCustomGatewayFilterFactory(){super(Config.class);// 绑定配置类}OverridepublicGatewayFilterapply(Configconfig){return(exchange,chain)-{log.info([Pre] CustomFilter, name{},config.getName());// Pre转发前returnchain.filter(exchange).then(Mono.fromRunnable(()-{log.info([Post] CustomFilter done);// Post响应后}));};}OverridepublicintgetOrder(){returnOrdered.LOWEST_PRECEDENCE;// order 越大优先级越低}DatapublicstaticclassConfig{privateStringname;// 对应 yml args.name}}5.2 yml 配置只对product-route生效spring:cloud:gateway:server:webflux:routes:-id:product-route# 路由 IDuri:lb://product-service# 目标服务predicates:-Path/product/**# 路径断言filters:-AddRequestHeaderX-Request-Source,gateway# 内置过滤器-name:Custom# 自定义过滤器类名前缀args:name:custom filter# 传入 Config.name对所有路由生效写到default-filtersspring:cloud:gateway:server:webflux:default-filters:-name:Custom# 全局默认自定义过滤器args:name:global customroutes:-id:order-routeuri:lb://order-servicepredicates:-Path/order/**5.3 带参过滤器 shortcut 写法可选参数只有一个时可用简写filters:-Customcustom filter# 等价于 name: Custom args.name需在工厂类中重写shortcutFieldOrder()指定参数顺序。六、自定义 GlobalFilter全局实现GlobalFilterOrdered无需 yml注册为 Bean 后对所有路由生效。packagecom.emrys.gateway.filter;importlombok.extern.slf4j.Slf4j;importorg.springframework.cloud.gateway.filter.GatewayFilterChain;importorg.springframework.cloud.gateway.filter.GlobalFilter;importorg.springframework.core.Ordered;importorg.springframework.stereotype.Component;importorg.springframework.web.server.ServerWebExchange;importreactor.core.publisher.Mono;Slf4jComponent// 注册为 Bean 即全局生效publicclassCustomGlobalFilterimplementsGlobalFilter,Ordered{OverridepublicMonoVoidfilter(ServerWebExchangeexchange,GatewayFilterChainchain){log.info([Pre] GlobalFilter path{},exchange.getRequest().getURI().getPath());// Pre转发前returnchain.filter(exchange).then(Mono.fromRunnable(()-{log.info([Post] GlobalFilter status{},exchange.getResponse().getStatusCode());// Post响应后}));}OverridepublicintgetOrder(){returnOrdered.HIGHEST_PRECEDENCE;// 数字小 优先执行}}6.1 常用 GlobalFilter 场景场景实现要点全链路 TraceIdPre 阶段生成 UUID写入请求 Header 并放入 MDC全站鉴权Pre 阶段校验 Token失败则exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED)并return exchange.getResponse().setComplete()请求耗时Pre 记录开始时间Post 计算差值打日志七、普通 vs 全局 对照示例同时启用 CustomGatewayFilterFactory仅 product-route和 CustomGlobalFilter 时日志顺序order 相同时[Pre] CustomFilter ← GatewayFilter 先 [Pre] GlobalFilter ← GlobalFilter 后 ... 后端处理 ... [Post] GlobalFilter [Post] CustomFilter八、完整接入步骤8.1 创建 Filter 类在gateway模块下新建包com.emrys.gateway.filter编写上述两个类。8.2 配置 GatewayFilter可选在application-dev.yml的目标路由filters中添加name: Custom。8.3 启动验证# 经网关访问 productGET http://localhost:9000/product/getProductById?id1观察 gateway 日志应出现 CustomFilter / GlobalFilter 的 Pre、Post 输出。九、GatewayFilter 与 GlobalFilter 选型需求推荐只作用于/product/**GatewayFilter只作用于某几条路由GatewayFilter分别配在各路由filters作用于全部路由GlobalFilter或default-filters GatewayFilter需要 yml 传参开关、阈值GatewayFilterConfig args纯代码逻辑、全局统一GlobalFilter十、常见问题10.1 yml 配了 Custom 但报 Unknown filter类名必须以GatewayFilterFactory结尾且类上有Component/Service。10.2 GlobalFilter 不生效检查是否注册为 Spring BeanComponent且未被Conditional排除。10.3 Pre 里如何中断请求exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);// 设置状态码returnexchange.getResponse().setComplete();// 直接结束不调用 chain.filter10.4 Boot 4 配置不生效确认使用spring.cloud.gateway.server.webflux.routes而非旧版spring.cloud.gateway.routes。十一、总结主题GatewayFilter普通GlobalFilter全局基类/接口AbstractGatewayFilterFactoryGlobalFilterOrdered命名XxxGatewayFilterFactory→ ymlname: Xxx任意类名配置ymlfilters/default-filters无需 yml范围按路由全部路由Pre/Postchain.filter前 /.then()后相同