Spring Cloud Gateway 之服务入口 — 自定义过滤器详解
(基于 Spring Cloud 2024.x / 2025.x 主流版本,2026年3月视角)
Spring Cloud Gateway 是目前最主流的第二代网关(非 Zuul),其过滤器机制是核心扩展点,几乎所有鉴权、日志、限流、请求/响应改写、灰度、WAF 等功能都靠自定义过滤器实现。
一、Gateway 过滤器三大类型对比(必背)
| 类型 | 作用范围 | 配置方式 | 是否需要 Ordered | 典型使用场景 | 实现接口/基类 |
|---|---|---|---|---|---|
| GlobalFilter | 全局(所有路由) | @Component / @Bean | 是(强烈推荐) | 统一鉴权、日志、跨域、请求ID追踪、限流兜底 | GlobalFilter + Ordered |
| GatewayFilter | 单路由 / 部分路由 | yml routes.filters 或 default-filters | 是(通过 OrderedGatewayFilter 包装) | 路由级别的特殊处理(如特定接口加 header) | AbstractGatewayFilterFactory → apply() 返回 GatewayFilter |
| GatewayFilterFactory | 可配置参数的路由级过滤器 | yml 中以 – Name=xxx,xxx 写法 | 可选 | 最常用:带参数的复用过滤器(如 AddHeader、限流、脱敏) | AbstractGatewayFilterFactory |
2026年推荐优先级:
- 需要全局统一处理 → GlobalFilter
- 需要带参数、路由级别复用 → 自定义 GatewayFilterFactory(最灵活)
- 极少数场景才直接手写 GatewayFilter(不带工厂)
二、最常用写法:自定义 GlobalFilter(全局鉴权 / 日志 / 请求追踪)
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.UUID;
@Component
public class RequestIdGlobalFilter implements GlobalFilter, Ordered {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
ServerHttpRequest request = exchange.getRequest();
// 1. 前置处理(pre filter)
String requestId = request.getHeaders().getFirst("X-Request-Id");
if (requestId == null) {
requestId = UUID.randomUUID().toString().replace("-", "");
}
// 放入 MDC 或 exchange 属性,供下游使用
exchange.getAttributes().put("X-Request-Id", requestId);
// 可记录开始时间
long startTime = System.currentTimeMillis();
// 2. 继续过滤链(相当于 chain.doFilter)
return chain.filter(exchange)
// 3. 后置处理(post filter)
.doFinally(signalType -> {
long cost = System.currentTimeMillis() - startTime;
// 可记录日志:请求路径、耗时、状态码等
System.out.printf("[Gateway] %s %s cost=%dms%n",
request.getMethod(), request.getURI(), cost);
});
}
/**
* 过滤器执行顺序:值越小越先执行
* 常见参考值:
* - NettyWriteResponseFilter = -1(写响应)
* - LoadBalancerClientFilter ≈ 10100(负载均衡)
* 建议:鉴权/日志放 -100 ~ 100 区间
*/
@Override
public int getOrder() {
return -100;
}
}
三、最灵活写法:自定义 GatewayFilterFactory(带配置参数)
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class AddCustomHeaderGatewayFilterFactory
extends AbstractGatewayFilterFactory<AddCustomHeaderGatewayFilterFactory.Config> {
public AddCustomHeaderGatewayFilterFactory() {
super(Config.class);
}
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
ServerHttpRequest req = exchange.getRequest().mutate()
.header(config.getHeaderName(), config.getHeaderValue())
.build();
return chain.filter(exchange.mutate().request(req).build());
};
}
@Override
public List<String> shortcutFieldOrder() {
// 快捷写法支持: - AddCustomHeader=X-Trace-Id, ${traceId}
return Arrays.asList("headerName", "headerValue");
}
public static class Config {
private String headerName;
private String headerValue;
// getter & setter
public String getHeaderName() { return headerName; }
public void setHeaderName(String headerName) { this.headerName = headerName; }
public String getHeaderValue() { return headerValue; }
public void setHeaderValue(String headerValue) { this.headerValue = headerValue; }
}
}
yml 配置方式(三种等价写法):
spring:
cloud:
gateway:
routes:
- id: user-service
uri: lb://user-service
predicates:
- Path=/user/**
filters:
# 方式1:完整类名(不推荐)
# - name: AddCustomHeaderGatewayFilterFactory
# args:
# headerName: X-Trace-Id
# headerValue: trace-${traceId}
# 方式2:简写(推荐,类名去掉 GatewayFilterFactory 后缀)
- AddCustomHeader=X-Trace-Id, trace-${traceId}
# 方式3:带参数的工厂写法
# - name: AddCustomHeader
# args:
# headerName: X-From
# headerValue: gateway
四、常见应用场景 & 推荐顺序值参考(2026主流)
| 场景 | 推荐类型 | 建议 order 值 | 说明 |
|---|---|---|---|
| 请求ID生成/追踪 | GlobalFilter | -200 ~ -100 | 最早放,便于全链路追踪 |
| 统一鉴权/JWT校验 | GlobalFilter | -50 ~ 0 | 在路由匹配后、转发前 |
| 限流/熔断 | GatewayFilterFactory | 100 ~ 200 | 可针对路由精细控制 |
| 请求/响应日志 | GlobalFilter | -150 / 900 | pre 记录开始,post 记录结束+耗时 |
| 添加/脱敏 Header | GatewayFilterFactory | 300 ~ 500 | 可配置化 |
| 响应包装/统一格式 | GlobalFilter | 900 ~ -2 | 晚于 -1(Netty写响应前) |
| CORS 跨域 | GlobalFilter 或内置 | -300 | 通常用 CorsWebFilter 或自定义 |
五、2026年避坑 & 最佳实践
- 顺序混乱 → 导致鉴权没生效、header没加 → 一定要实现 Ordered 并合理赋值
- 阻塞操作 → 禁止在 filter 里用 Thread.sleep、JDBC、同步HTTP → 用 Mono/Flux 异步
- 重复读取 body → 需要缓存请求体用
ServerWebExchangeDecorator+modifyRequestBody - 生产关闭调试日志 → logging.level.org.springframework.cloud.gateway=INFO
- 优先使用内置过滤器 → RewritePath、AddRequestHeader、RequestRateLimiter、Retry 等
- 异步友好 → 所有自定义 filter 都返回 Mono,避免 blocking
你现在想实现哪种具体过滤器?
- JWT / Token 统一校验
- 请求响应全链路日志 + traceId
- 响应体统一包装(类似 R)
- IP 黑白名单 / 限流
- Header 参数脱敏 / 添加签名
告诉我场景 + 需求,我直接给你完整可运行代码(包括 yml 配置 + 测试方式)。