Spring Cloud Gateway 的内置路由过滤器(Built-in Route Filters)是网关核心功能之一,用于对请求 / 响应进行拦截和处理(如修改请求头、添加响应头、路径重写、限流等),无需自定义代码即可满足大部分常见场景。
内置过滤器分为两类:
- GatewayFilter:单路由生效(仅对配置的路由起作用)。
- GlobalFilter:全局生效(对所有路由起作用,如负载均衡、熔断等,部分内置全局过滤器默认启用)。
本文重点讲解 单路由级内置 GatewayFilter 的使用,按场景分类说明配置方式(基于 YAML 配置,properties 类似)。
一、核心配置格式
内置过滤器通过 routes.filters 配置,格式为:
yaml
spring:
cloud:
gateway:
routes:
- id: 路由ID(唯一)
uri: 目标服务地址(如 lb://服务名、http://ip:端口)
predicates: # 路由匹配条件(如路径、方法)
- Path=/api/**
filters: # 内置过滤器配置(数组形式,顺序即执行顺序)
- 过滤器名=参数1,参数2,... # 有参数的过滤器
- 过滤器名 # 无参数的过滤器
二、常用内置过滤器分类详解
1. 请求头 / 响应头操作
用于添加、修改、移除请求头或响应头,常见场景:传递身份信息、跨域配置、隐藏敏感响应头。
| 过滤器名 | 作用 | 参数格式 | 示例 |
|---|---|---|---|
| AddRequestHeader | 给请求添加头 | AddRequestHeader = 头名,头值 | - AddRequestHeader=X-Request-Source,gateway |
| AddResponseHeader | 给响应添加头 | AddResponseHeader = 头名,头值 | - AddResponseHeader=X-Response-Time,${currentTime} |
| RemoveRequestHeader | 移除请求头 | RemoveRequestHeader = 头名 | - RemoveRequestHeader=Cookie |
| RemoveResponseHeader | 移除响应头 | RemoveResponseHeader = 头名 | - RemoveResponseHeader=X-Powered-By |
| SetRequestHeader | 覆盖请求头(无则添加) | SetRequestHeader = 头名,头值 | - SetRequestHeader=Content-Type,application/json |
| SetResponseHeader | 覆盖响应头(无则添加) | SetResponseHeader = 头名,头值 | - SetResponseHeader=Cache-Control,no-cache |
| RewriteResponseHeader | 正则替换响应头值 | RewriteResponseHeader = 头名,正则,替换值 | - RewriteResponseHeader=Location,http://old.com,https://new.com |
示例:给请求添加来源头,移除响应的敏感头
yaml
spring:
cloud:
gateway:
routes:
- id: header-demo
uri: lb://user-service
predicates:
- Path=/user/**
filters:
- AddRequestHeader=X-Gateway-Id,user-route-01
- RemoveResponseHeader=X-Powered-By # 隐藏服务技术栈
2. 路径重写(最常用)
用于修改请求路径,解决 "网关路径与服务实际路径不一致" 问题(如网关 /api/user/** 转发到服务 /user/**)。
| 过滤器名 | 作用 | 参数格式 | 说明 |
|---|---|---|---|
| RewritePath | 正则替换请求路径 | RewritePath = 原始正则,目标路径 | $n 表示原始路径中第 n 个分组(正则捕获) |
核心规则:
- 原始正则:匹配网关接收的路径(如
/api/(?<segment>.*),(?<segment>.*)是命名分组,也可简化为(.*))。 - 目标路径:替换后的路径(如
/$\{segment}或/$1,注意 YAML 中$需转义为$\)。
示例 1 :网关路径 /api/user/1 转发到服务 /user/1
yaml
spring:
cloud:
gateway:
routes:
- id: rewrite-path-demo
uri: lb://user-service
predicates:
- Path=/api/user/** # 匹配网关路径
filters:
# 正则:/api/(user/.*) → 分组1为 user/.*;目标路径:/$1 → 替换为 /user/.*
- RewritePath=/api/(user/.*),/$\{1}
示例 2 :统一前缀裁剪(网关 /gateway/** 转发到服务 /)
yaml
filters:
- RewritePath=/gateway/(?<segment>.*),/$\{segment} # /gateway/hello → /hello
3. 路径前缀操作
简化路径重写,支持 "添加前缀" 或 "移除前缀",比 RewritePath 更简洁。
| 过滤器名 | 作用 | 参数格式 | 示例 |
|---|---|---|---|
| PrefixPath | 给请求路径添加前缀(转发到服务时) | PrefixPath = 前缀 | - PrefixPath=/user(网关 /1 → 服务 /user/1) |
| StripPrefix | 移除路径前缀(从左到右移除 N 级) | StripPrefix=N(N 为整数) | - StripPrefix=1(网关 /api/1 → 服务 /1) |
示例 1 :StripPrefix(移除 1 级前缀)网关路径 /user/api/1 → 服务路径 /api/1(移除 /user 前缀):
yaml
routes:
- id: strip-prefix-demo
uri: lb://user-service
predicates:
- Path=/user/**
filters:
- StripPrefix=1 # 移除第1级前缀(/user)
示例 2 :PrefixPath(添加前缀)网关路径 /1 → 服务路径 /user/1(添加 /user 前缀):
yaml
routes:
- id: prefix-path-demo
uri: lb://user-service
predicates:
- Path=/**
filters:
- PrefixPath=/user # 添加前缀 /user
4. 超时配置
控制请求的超时时间(连接超时、响应超时),避免网关因服务响应慢而阻塞。
| 过滤器名 | 作用 | 参数格式 | 示例 |
|---|---|---|---|
| RequestTimeoute | 设置请求超时时间 | RequestTimeoute = 超时时间(如 3s) | - RequestTimeoute=3000ms(3 秒超时) |
示例:设置 3 秒超时,超时后网关返回 504 Gateway Timeout:
yaml
routes:
- id: timeout-demo
uri: lb://slow-service
predicates:
- Path=/slow/**
filters:
- RequestTimeoute=3s # 支持 s(秒)、ms(毫秒)
5. 重试机制
当服务暂时不可用(如 5xx 错误、连接超时)时,自动重试请求,提高可用性。
| 过滤器名 | 作用 | 参数格式(多参数用逗号分隔) | 说明 |
|---|---|---|---|
| Retry | 配置重试策略 | Retry = 重试次数,状态码,方法,延迟时间,最大延迟,因子 | 可选参数:- 重试次数(默认 3)- 触发重试的状态码(如 503)- 触发重试的 HTTP 方法(如 GET)- 初始延迟(默认 10ms)- 最大延迟(默认 1s)- 延迟因子(默认 2,指数退避) |
示例:GET 请求遇到 503/504 时,重试 2 次(初始延迟 100ms,指数退避):
yaml
routes:
- id: retry-demo
uri: lb://user-service
predicates:
- Path=/user/**
filters:
- Retry=2,503,504,GET,100ms,1s,2
# 含义:重试2次,仅对 GET 方法、状态码 503/504 触发,初始延迟100ms,最大延迟1s,延迟因子2(100ms → 200ms → 400ms,不超过1s)
6. 重定向
将请求重定向到其他 URL(如 HTTP 转 HTTPS、旧路径重定向到新路径)。
| 过滤器名 | 作用 | 参数格式 | 示例 |
|---|---|---|---|
| RedirectTo | 重定向(支持 3xx 状态码) | RedirectTo = 状态码,目标 URL | - RedirectTo=302,https://new-domain.com${path} |
参数说明:
- 状态码:301(永久重定向)、302(临时重定向)。
- 目标 URL:支持占位符
${path}(原始路径)、${query}(原始查询参数)。
示例 1:HTTP 转 HTTPS
yaml
routes:
- id: http-to-https
uri: http://localhost:8080
predicates:
- Path=/**
- Scheme=http # 仅匹配 HTTP 请求
filters:
- RedirectTo=302,https://$\{host}${path}${query} # 重定向到 HTTPS 同路径
示例 2:旧路径重定向到新路径
yaml
routes:
- id: old-to-new-path
uri: http://localhost:8080
predicates:
- Path=/old/**
filters:
- RedirectTo=301,/new$\{path} # /old/1 → /new/old/1
7. 限流(Rate Limiting)
限制单位时间内的请求数,保护后端服务,基于 Spring Cloud Gateway 集成的限流组件(如 Redis)。
前置条件:
- 引入 Redis 依赖(限流需要 Redis 存储计数器):
xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
- 配置 Redis 连接:
yaml
spring:
redis:
host: localhost
port: 6379
password: 123456
限流过滤器:RequestRateLimiter
| 过滤器名 | 作用 | 参数格式 | 说明 |
|---|---|---|---|
| RequestRateLimiter | 基于令牌桶算法限流 | RequestRateLimiter=key-resolver,replenishRate,burstCapacity | - key-resolver:限流键解析器(如 IP、用户 ID)- replenishRate:令牌桶填充速率(每秒允许的平均请求数)- burstCapacity:令牌桶最大容量(每秒允许的峰值请求数) |
步骤 1:定义限流键解析器(Java 代码)
需自定义 KeyResolver Bean,指定限流维度(如 IP、用户 ID):
java
运行
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;
@Configuration
public class RateLimitConfig {
// 基于请求IP限流(最常用)
@Bean
public KeyResolver ipKeyResolver() {
return exchange -> Mono.just(
exchange.getRequest().getRemoteAddress().getAddress().getHostAddress()
);
}
// 基于用户ID限流(需从请求头获取用户ID)
@Bean
public KeyResolver userIdKeyResolver() {
return exchange -> Mono.justOrEmpty(
exchange.getRequest().getHeader("X-User-Id")
).defaultIfEmpty("anonymous"); // 未登录用户设为匿名
}
}
步骤 2:配置限流过滤器
yaml
spring:
cloud:
gateway:
routes:
- id: rate-limit-demo
uri: lb://user-service
predicates:
- Path=/user/**
filters:
# 基于IP限流:每秒填充2个令牌,最大容量4个(峰值4QPS)
- RequestRateLimiter=ipKeyResolver,2,4
限流响应:默认返回 429 Too Many Requests。
8. 其他常用过滤器
| 过滤器名 | 作用 | 示例 |
|---|---|---|
| SetPath | 直接设置请求路径(覆盖原始路径) | - SetPath=/fixed-path(所有匹配请求都转发到 /fixed-path) |
| AddRequestParameter | 给请求添加查询参数 | - AddRequestParameter=type,web(请求添加 ?type=web) |
| RemoveRequestParameter | 移除请求查询参数 | - RemoveRequestParameter=secret(移除 ?secret=xxx) |
| DedupeResponseHeader | 去重响应头(避免重复值) | - DedupeResponseHeader=Access-Control-Allow-Credentials,RETAIN_FIRST(保留第一个值) |
三、过滤器执行顺序
- 同路由的过滤器按
filters数组中的配置顺序执行(先配置先执行)。 - 全局过滤器(GlobalFilter)与单路由过滤器的执行顺序由
@Order注解或getOrder()方法决定(值越小越先执行)。
四、注意事项
- 过滤器参数中若包含特殊字符(如
$、{、}),YAML 配置需转义(如$\{1}而非$1)。 - 路径匹配是 "贪婪匹配",路由 ID 需唯一,避免路由冲突。
- 限流、重试等过滤器需依赖额外组件(如 Redis),需提前引入依赖并配置。
- 尽量使用内置过滤器,避免自定义过滤器带来的维护成本;复杂场景(如自定义业务逻辑)可结合自定义过滤器。
总结
Spring Cloud Gateway 内置过滤器覆盖了路径处理、头操作、超时、重试、限流等核心场景,配置简单灵活。使用时需根据业务需求选择合适的过滤器,按 "路由 ID → 匹配条件 → 过滤器链" 的结构配置,注意执行顺序和参数格式。
如果需要更复杂的逻辑(如自定义权限校验、日志记录),可在内置过滤器基础上扩展自定义 GatewayFilter 或 GlobalFilter。