大家好,我是小富~
我發現公司的網關項目裏有很多的輪子,幾乎每個人接手這個項目開發,都會自定義過濾器,導致有非常非常多的過濾器,修改其中一個,指不定就會影響其他的人功能,非常的惱火。
其實在 Spring Cloud Gateway 本身內置了很多通用的過濾器組件,有些功能無需重複開發,直接通過配置就能完成請求修改、參數處理、安全校驗等功能。但遺憾的是,很多同學只知道 RewritePath 等常用過濾器,卻忽略了官方早已內置的 30+ 過濾器。
下邊小富梳理 Spring Cloud Gateway 30+ 個過濾器,包含配置示例與實戰場景,你會發現有些代碼真的不用寫。
一、請求相關
1. AddRequestHeader
作用:給請求添加 Header,轉發請求前,給請求添加指定 Header。
配置示例:
spring:
cloud:
gateway:
routes:
- id: xiaofu-120412
uri: http://127.0.0.1:12041/
predicates:
- Weight=xiaofu-group, 1
- Path=/test/version1/**
filters:
- RewritePath=/test/version1/(?<segment>.*),/$\{segment}
- name: AddRequestHeader
args:
name: X-Request-Source # Header名稱
value: gateway # Header值
場景:傳遞請求來源標識(如gateway、app),方便下游服務做權限控制。
2. RemoveRequestHeader
作用:移除請求中的 Header,轉發前移除請求中指定的 Header(如敏感信息)。
配置示例:
filters:
- RewritePath=/test/version1/(?<segment>.*),/$\{segment}
- name: RemoveRequestHeader
args:
name: Authorization # 移除客户端傳來的 Authorization 頭
場景:下游服務不需要客户端直接傳遞的令牌,由網關統一處理認證時使用。
3. SetRequestHeader
作用:覆蓋請求中的 Header,若請求中已存在指定 Header,直接覆蓋其值;不存在則添加。
配置示例:
filters:
- RewritePath=/test/version1/(?<segment>.*),/$\{segment}
- name: SetRequestHeader
args:
name: Authorization
value: 111111 # 強制將 Authorization 設為 111111
注意:與 AddRequestHeader 的區別是,SetRequestHeader 會覆蓋原有值,而 AddRequestHeader 會保留原有值(若存在)。
4. AddRequestParameter
作用:轉發請求時給請求添加參數,URL 或請求體添加參數(支持 GET/POST)。
配置示例:
filters:
- RewritePath=/test/version1/(?<segment>.*),/$\{segment}
- name: AddRequestParameter
args:
name: from
value: gateway # 所有請求會帶上 ?from=gateway 參數
場景:統計請求來源,或給下游服務傳遞額外標識(如灰度標記)。
5. RemoveRequestParameter
作用:移除請求中的參數,轉發前移除請求中的指定參數(如敏感參數 password)。
配置示例:
filters:
- RewritePath=/test/version1/(?<segment>.*),/$\{segment}
- name: RemoveRequestParameter
args:
name: password # 移除請求中的 password 參數
6. MapRequestHeader
作用:把網關請求頭的值,映射到另一個請求頭裏。比如前端調用網關,請求頭有一個 X-User-Id 用來驗證,但是要轉發的下游服務只校驗請求頭 userId,這時要自動做一個映射。
配置示例:
filters:
- MapRequestHeader=X-User-Id, userId
7. RequestSize
作用:限制請求體大小,拒絕請求體超過指定大小的請求(防止大文件上傳壓垮服務)。
配置示例:
filters:
- name: RequestSize
args:
maxSize: 10MB # 最大請求體10MB,超過返回413
8. RequestHeaderSize
作用:限制請求頭大小,拒絕請求頭超過指定大小的請求,如下任何請求頭的大小超過1000字節,這將發送一個 431狀態碼的響應。
配置示例:
filters:
- RequestHeaderSize=1000B
9. PreserveHostHeader
作用:保留原始 Host 頭,轉發請求時,保留客户端的原始 Host 頭(默認會改為下游服務的 Host)。
配置示例:
filters:
- name: PreserveHostHeader # 無參數,直接啓用
- 場景:下游服務依賴 Host 頭進行邏輯處理時使用。
10. SetRequestHostHeader
作用:某些情況下,host 頭可能需要被重寫。修改請求的 Host 頭,轉發請求時,強制修改 Host 頭為指定值。
配置示例:
filters:
- name: SetRequestHostHeader
args:
host: target-service.com # 強制 Host 頭為 target-service.com
11. CacheRequestBody
作用:緩存請求體,請求體(如 POST 請求的 JSON 數據),我們知道默認請求體只能讀一次,所以為了後續的操作,使用該過濾器來緩存請求體,然後再把它發送到下游,從 exchange 屬性中獲取請求體。
配置示例:
filters:
- name: CacheRequestBody
args:
cacheName: requestBodyCache # 緩存名稱
場景:多個過濾器需要讀取請求體時使用(如先校驗簽名,再解析參數)。
二、響應相關
主要是調整服務返回的響應信息,比如響應頭 Header 等。
1. AddResponseHeader
作用:給響應添加 Header,服務返回響應後,給響應添加指定 Header(如跨域標識、緩存控制)。
配置示例:
filters:
- RewritePath=/test/version1/(?<segment>.*),/$\{segment}
- name: AddResponseHeader
args:
name: X-Response-Time
value: 120 # 可結合全局過濾器動態設置響應時間
場景:添加 Cache-Control: max-age=3600 控制靜態資源緩存。
2. RemoveResponseHeader
作用:移除響應中的 Header,移除服務返回的敏感響應頭(如 X-Application-Context 暴露服務信息)。
配置示例:
filters:
- RewritePath=/test/version1/(?<segment>.*),/$\{segment}
- name: RemoveResponseHeader
args:
name: X-Application-Context
3. SetResponseHeader
作用:覆蓋響應中的 Header,覆蓋服務返回的響應頭(如統一設置 Content-Encoding)。
配置示例:
filters:
- RewritePath=/test/version1/(?<segment>.*),/$\{segment}
- name: SetResponseHeader
args:
name: Content-Encoding
value: gzip # 強制響應使用 gzip 編碼
4. RewriteResponseHeader
作用:重寫響應 Header 的值,用正則表達式修改響應 Header 的值(如脱敏處理)。
配置示例:
filters:
- RewritePath=/test/version1/(?<segment>.*),/$\{segment}
- name: RewriteResponseHeader
args:
name: X-User-Phone
regexp: "(.{3}).\*(.{4})" # 保留前3位和後4位
replacement: "\$1\*\*\*\*\$2" # 手機號脱敏為 138\*\*\*\*5678
5. DedupeResponseHeader
作用:去重響應頭,當響應頭存在多個相同名稱時,去重並保留指定值。
配置示例:
filters:
- RewritePath=/test/version1/(?<segment>.*),/$\{segment}
- name: DedupeResponseHeader
args:
name: Access-Control-Allow-Origin
strategy: RETAIN\_FIRST # 保留第一個值
場景:解決跨域配置中 Access-Control-Allow-Origin 重複的問題。
6. RemoveJsonAttributesResponseBody
作用:從根層 JSON 響應結果中移除指定字段,只對 Content-Type: application/json 的響應生效。
配置示例:
filters:
- RewritePath=/test/version1/(?<segment>.*),/$\{segment}
- RemoveJsonAttributesResponseBody=xiaofu
場景:比如在某些敏感或無意義的字段,下游服務暫時無法改動,而響應結果又不想暴漏出來的字段。注意:2021.x版本的網關還不支持,需要高版本。
7. SetStatus:設置響應狀態碼
作用:強制修改響應的 HTTP 狀態碼(如將 404 改為 200 並返回自定義提示)。
配置示例:
filters:
- name: SetStatus
args:
status: 200 # 無論服務返回什麼,響應狀態碼都設為 200
8. RewriteLocationResponseHeader
作用:重寫響應頭中的 Location(用於反向代理場景)。
NEVER_STRIP、AS_IN_REQUEST(默認)和 ALWAYS_STRIP。
- NEVER_STRIP: 即使最初的請求路徑不包含version,version也不會被剝離。
- AS_IN_REQUEST: 只有當原始請求路徑不包含version時,才會剝離version。
- ALWAYS_STRIP: version 總是被剝離,即使原始請求路徑包含version 。
配置示例:
filters:
- RewriteLocationResponseHeader=AS_IN_REQUEST, Location
三、路徑處理相關
修改請求路徑與跳轉相關的操作
1. RewritePath(最常用)
作用:重寫請求路徑,用正則表達式修改請求路徑(如去掉 /api 前綴)。
配置示例:
filters:
- name: RewritePath
args:
regexp: /api/(?\<segment>.\*) # 匹配 /api/test
replacement: /\$\\{segment} # 重寫為 /test(轉發到下游服務)
場景:前端請求帶 /api 前綴,網關轉發時去掉,適配下游服務接口路徑。
2. PrefixPath
作用:給路徑添加前綴,轉發前給請求路徑添加指定前綴(如下游服務接口統一帶 /v1)。
配置示例:
filters:
- name: PrefixPath
args:
prefix: /v1 # 請求 /user → 轉發到 /v1/user
3. StripPrefix
作用:移除路徑前綴,移除路徑中指定數量的前綴段(如 /api/v1/user 移除 2 段前綴)。
配置示例:
filters:
- name: StripPrefix
args:
parts: 2 # /api/v1/user → 轉發到 /user
注意:與 RewritePath 的區別是,StripPrefix 按段數移除,RewritePath 按正則匹配,更靈活。
4. RedirectTo
作用:重定向請求,將請求重定向到指定 URL(支持 301/302 狀態碼)。
配置示例:
filters:
- name: RedirectTo
args:
status: 302 # 臨時重定向
url: https://baidu.com # 重定向到新域名
場景:域名遷移、舊接口廢棄時引導到新地址。
5. SetPath
作用:直接設置路徑,用模板語法直接設置請求路徑(替代原有路徑)。
配置示例:
filters:
- name: SetPath
args:
template: /fixed/path # 所有請求都轉發到 /fixed/path
四、安全相關:
控制請求參數與路由轉發相關的操作,比如請求限流、重試、負載均衡等。
1. RequestRateLimiter
作用:基於令牌桶算法限流(默認用 Redis 存儲限流計數)。
配置示例:
filters:
- RewritePath=/test/version1/(?<segment>.*),/$\{segment}
- name: RequestRateLimiter
args:
redis-rate-limiter.replenishRate: 10 # 令牌桶填充速率(每秒10個)
redis-rate-limiter.burstCapacity: 20 # 令牌桶最大容量(最多存20個)
key-resolver: "#{@myKeyResolver}" # 需自定義 KeyResolver
key-resolver 用於定義如何生成限流的key,這通常基於請求的某些屬性(如IP地址、用户ID等)。你可以通過實現 KeyResolver 接口來自定義key解析器。
import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component("myKeyResolver")
public class MyKeyResolver implements KeyResolver {
@Override
public Mono<String> resolve(ServerWebExchange exchange) {
// 例如,根據請求頭中的某個字段生成key
return Mono.just("8888888x-api-key:"+exchange.getRequest().getHeaders().getFirst("x-api-key"));
}
}
由於默認是 redis 做底層限流,所以這裏要加上 redis 配置信息
spring:
redis:
host: localhost
port: 6379
password: xxxx
場景:保護下游服務,防止流量過載(如秒殺接口限制單 IP 訪問頻率)。
2. Retry
作用:請求重試,當服務返回指定狀態碼或超時,自動重試請求。
配置示例:
filters:
- name: Retry
args:
retries: 3 # 最多重試3次
statuses: BAD_GATEWAY, SERVICE_UNAVAILABLE # 遇到 502/503 重試
methods: GET,POST
backoff:
firstBackoff: 10ms # 第一次重試延遲100ms
maxBackoff: 50ms # 最大延遲1s
factor: 2 # 延遲倍數(100ms → 200ms → 400ms)
basedOnPreviousValue: false
注意:重試可能導致下游服務重複處理,需確保接口冪等性。
3. Hystrix
作用:熔斷降級(已過時,推薦 CircuitBreaker),服務調用超時或失敗時,觸發熔斷並返回降級響應。
配置示例:
filters:
- name: Hystrix
args:
name: fallbackCommand # 熔斷命令名
fallbackUri: forward:/fallback # 降級接口(返回默認數據)
4. CircuitBreaker
作用:熔斷降級(替代 Hystrix),基於 Resilience4j 實現熔斷,支持超時、失敗率閾值配置。
配置示例:
filters:
- name: CircuitBreaker
args:
name: myCircuitBreaker
fallbackUri: forward:/inCaseOfFailureUseThis # 這裏是網關內的控制器uri
statusCodes: # 也可根據狀態來控制是否熔斷
- 500
- "NOT_FOUND"
@RestController
@RequestMapping("/")
@Slf4j
public class InCaseOfFailureUseThisController {
@GetMapping(value = "/inCaseOfFailureUseThis")
public String inCaseOfFailureUseThis() {
System.out.println("inCaseOfFailureUseThis");
return "inCaseOfFailureUseThis";
}
}
如果我們希望熔斷後不路由到網關,而且是轉發到其他的外部路徑,可以如下設置。
spring:
cloud:
gateway:
routes:
- id: ingredients
uri: http://127.0.0.1:12041/
predicates:
- Path=//ingredients/**
filters:
- name: CircuitBreaker
args:
name: myCircuitBreaker
fallbackUri: forward:/fallback
- id: myCircuitBreaker-fallback
uri: http://localhost:9994
predicates:
- Path=/fallback
5. SaveSession
在轉發調用下游之前強制進行 WebSession::save 操作,這在使用類似 Spring Session 的懶數據存儲時特別有用,因為你需要確保在進行轉發調用之前已經保存了Session狀態。
配置示例:
filters:
- SaveSession
如果集成了 Spring Security 與 Spring Session ,而且希望確保安全細節已被轉發到下游進程,這一點至關重要。
寫在最後
這期東西還是很多的,其實 80% 的路由增強場景(如路徑重寫、限流、跨域)都能通過內置過濾器實現,無需手寫代碼,所有不要動不動就想着加過濾器。還有在使用過濾器的時候要注意,多個過濾器的配置順序,順序不對容易出奇奇怪怪的問題哦。