📌 一、什么是 Gateway 的斷言(Predicates)?
Predicates(斷言) 是 Spring Cloud Gateway 中用于匹配請求的條件。只有請求滿足斷言條件,路由才會生效,轉發到下游服務。
🎯 二、常見內置斷言類型
斷言類型 示例配置 對應斷言工廠類 說明 Path
Path=/api/**
PathRoutePredicateFactory
匹配請求路徑(支持通配符) Method
Method=GET
MethodRoutePredicateFactory
匹配請求方法(GET、POST等) Header
Header=Auth, \w+
HeaderRoutePredicateFactory
匹配請求頭,支持正則 Query
Query=token
QueryRoutePredicateFactory
匹配 URL 查詢參數(?key=value) Host
Host=**.example.com
HostRoutePredicateFactory
匹配請求 Host(域名) Cookie
Cookie=sessionId, \w+
CookieRoutePredicateFactory
匹配請求中的 Cookie RemoteAddr
RemoteAddr=192.168.0.1/24
RemoteAddrRoutePredicateFactory
匹配客戶端 IP(支持 CIDR) After
After=2025-08-01T00:00:00+08:00
AfterRoutePredicateFactory
匹配某個時間之后的請求 Before
Before=2025-09-01T00:00:00+08:00
BeforeRoutePredicateFactory
匹配某個時間之前的請求 Between
Between=2025-08-01T00:00:00+08:00, 2025-08-31T23:59:59+08:00
BetweenRoutePredicateFactory
匹配時間范圍內的請求 Weight
Weight=group1, 80
WeightRoutePredicateFactory
灰度發布、流量權重控制
📦 三、斷言使用方式(YAML 示例)
spring:cloud:gateway:routes:- id: user_routeuri: http://localhost:8081predicates:- Path=/user/**- Method=GET
🧱 四、自定義斷言的必要性
當內置斷言不能滿足個性化業務需求時,例如:
用戶權限判斷
參數動態校驗
黑白名單過濾
特定設備訪問限制
就需要創建自定義斷言。
🔧 五、自定義斷言步驟(按請求參數控制)
? 目標:
只有當請求參數中
allow=true
時才允許路由。
📄 第一步:創建斷言類
注意對于:
//是1 return new Predicate<ServerWebExchange>() { //還是2 return new GatewayPredicate() {return new GatewayPredicate() {@Overridepublic boolean test(ServerWebExchange exchange) {String value = exchange.getRequest().getQueryParams().getFirst(config.getParam());return config.getExpectedValue() != null && config.getExpectedValue().equals(value);}
2.0.x.RELEASE
:? 有Predicate<ServerWebExchange>
,但沒有GatewayPredicate
。
2.1.0.RELEASE
及以后:? 增加了GatewayPredicate
接口,用于擴展斷言工廠。package com.example.gateway.predicates;import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange;import java.util.function.Predicate;@Component public class AllowParamRoutePredicateFactoryextends AbstractRoutePredicateFactory<AllowParamRoutePredicateFactory.Config> {public AllowParamRoutePredicateFactory() {super(Config.class);}//方式一 Lambda 表達式形式@Overridepublic Predicate<ServerWebExchange> apply(Config config) {return exchange -> {String value = exchange.getRequest().getQueryParams().getFirst(config.getParam());return config.getExpectedValue() != null && config.getExpectedValue().equals(value);};}//方式二 匿名內部類形式@Overridepublic Predicate<ServerWebExchange> apply(Config config) {return new Predicate<ServerWebExchange>() {@Overridepublic boolean test(ServerWebExchange exchange) {String value = exchange.getRequest().getQueryParams().getFirst(config.getParam());return config.getExpectedValue() != null && config.getExpectedValue().equals(value);}}; }@Overridepublic List<String> shortcutFieldOrder() {return Arrays.asList("param", "expectedValue");}@Data@NoArgsConstructorpublic static class Config {private String param;private String expectedValue;} }
🧾 第二步:配置文件中使用
spring:cloud:gateway:routes:- id: allow_param_routeuri: http://localhost:8081predicates:#這個名稱必須與AllowParamRoutePredicateFactory所匹配否則匹配不上#也就是說自定義攔截器叫HhRoutePredicateFactory#下面也要寫成Hh=name,value - AllowParam=allow, true
🧪 第三步:訪問測試
?
http://localhost:9000/test?allow=true
→ 匹配成功,轉發到下游服務?
http://localhost:9000/test?allow=false
→ 匹配失敗,不轉發
🧠 六、重點解釋:值是怎么傳入 config 的?
配置值注入原理:
Spring Boot 自動讀取
AllowParamRoutePredicateFactory
類發現其內部的
Config
類中包含字段:param
和expectedValue
調用方法:
@Override public List<String> shortcutFieldOrder() {return Arrays.asList("param", "expectedValue"); }
YAML 配置:
AllowParam=allow, true
?? 會自動賦值為:
config.param = "allow"; config.expectedValue = "true";
🧠 七、兩行核心邏輯詳解
String value = exchange.getRequest().getQueryParams().getFirst(config.getParam()); return config.getExpectedValue().equals(value);
第一句:從請求參數中取出
config.param
指定的參數名的值第二句:判斷這個值是否等于配置中
expectedValue
🔒 八、為什么寫成斷言而不是過濾器?
對比項 斷言(Predicate) 過濾器(Filter) 作用時機 匹配路由前 路由匹配之后 是否轉發 決定是否進入路由 已經進入路由,處理請求/響應 使用目的 控制路由是否生效(入門條件) 日志、限流、鑒權、響應處理等增強功能 推薦用途 參數控制、角色控制、AB測試等 認證授權、限流、Header 修改、響應包裝等
? 九、總結
項目 內容 自定義斷言基類 AbstractRoutePredicateFactory
配置值映射方式 shortcutFieldOrder()
定義參數順序觸發時機 請求進入網關、匹配路由之前 使用場景 請求參數判斷、設備識別、用戶等級判斷等 與 Filter 區別 Predicate 決定“要不要路由”,Filter 是增強 核心邏輯建議 加入 null 判斷,防止 NPE
🧰 十、可擴展場景建議
業務場景 自定義斷言建議邏輯 按用戶權限分流 從 JWT 中解析權限字段,判斷是否匹配 灰度發布 用戶 ID 做 hash 取模,實現 10% 的灰度流量 手機訪問攔截 通過 User-Agent 判斷是否來自移動端 限制訪問時間 判斷當前時間是否處于營業時間