寫在前面 本文參考以下文章,請參考原文
springcloud(十五):服務網關 Spring Cloud GateWay 入門
Predicate & Spring Cloud Gateway 路由匹配規則
Predicate 來源於 Java 8,是 Java 8 中引入的一個函數,Predicate 接受一個輸入參數,返回一個布爾值結果。該接口包含多種默認方法來將 Predicate 組合成其他復雜的邏輯(比如:與,或,非)。可以用於接口請求參數校驗、判斷新老數據是否有變化需要進行更新操作。
在 Spring Cloud Gateway 中 Spring 利用 Predicate 的特性實現了各種路由匹配規則,有通過 Header、請求參數等不同的條件來進行作為條件匹配到對應的路由。
在Spring Cloud Gateway--網關路由 簡單示例了Spring Cloud Gateway的路由功能,現在講一下Spring Cloud Gateway的路由規則。
1.通過時間匹配(datetime)
通過配置predicated 的 Before ,After ,Between 等屬性,可以實現限制路由轉發的時間段。時間對比:Spring 是通過 ZonedDateTime 來對時間進行的對比,ZonedDateTime 是 Java 8 中日期時間功能里,用於表示帶時區的日期與時間信息的類,ZonedDateTime 支持通過時區來設置時間,中國的時區是:Asia/Shanghai
- Before Route Predicate 剛好相反,在某個時間之前的請求的請求都進行轉發
- After Route Predicate 是指在這個時間之后的請求都轉發到目標地址
- Between Route Predicate 只有在這段時間內的請求才進行轉發
在Spring Cloud Gateway--網關路由 的例子基礎上修改application.yml如下,就表示在這個時間之前可以進行路由,在這時間之后停止路由,修改完之后重啟項重新啟動網關服務,訪問http://localhost:8080/discoveryClient,頁面會報 404 沒有找到地址
server:
port: 8080
spring:
cloud:
gateway:
routes:
- id: neo_route
uri: http://localhost:2001/
predicates:
- Path=/discoveryClient
- Before=2020-12-01T06:06:06+08:00[Asia/Shanghai]
修改application.yml如下,就表示在這個時間之后的時間可以進行路由,修改完之后重啟項重新啟動網關服務,訪問http://localhost:8080/discoveryClient,會自動路由到 http://localhost:2001/discoveryClient
server:
port: 8080
spring:
cloud:
gateway:
routes:
- id: neo_route
uri: http://localhost:2001/
predicates:
- Path=/discoveryClient
- After=2020-21-01T06:06:06+08:00[Asia/Shanghai]
修改application.yml如下,就表示只有這個時間段內 可以進行路由,修改完之后重啟項重新啟動網關服務,訪問http://localhost:8080/discoveryClient,會自動路由到 http://localhost:2001/discoveryClient
server:
port: 8080
spring:
cloud:
gateway:
routes:
- id: neo_route
uri: http://localhost:2001/
predicates:
- Path=/discoveryClient
- Between=2020-12-01T06:06:06+08:00[Asia/Shanghai], 2020-12-16T06:06:06+08:00[Asia/Shanghai]
2.通過Cookie匹配(Cookie)
Cookie Route Predicate 可以接收兩個參數,一個是 Cookie name ,一個是正則表達式,路由規則會通過獲取對應的 Cookie name 值和正則表達式去匹配,如果匹配上就會執行路由,如果沒有匹配上則不執行。
server:
port: 8080
spring:
cloud:
gateway:
routes:
- id: neo_route
uri: http://localhost:2001/
predicates:
- Path=/discoveryClient
- Cookie=name, mtest
使用curl命令測試,可以看到帶cookie的請求可以正確路由,正常獲取到頁面返回值,不帶cookie的請求會404
C:\Users\mm>curl http://localhost:8080/discoveryClient --cookie "ityouknow=kee.e"
Services: []
C:\Users\mm>curl http://localhost:8080/discoveryClient
{"timestamp":"2020-12-09T03:48:44.034+00:00","path":"/discoveryClient","status":404,"error":"Not Found","message":null,"requestId":"80c9666b-1"}
3.通過 Header 屬性匹配(Header)
Header Route Predicate也是接收 2 個參數,一個 header 中屬性名稱和一個正則表達式,這個屬性值和正則表達式匹配則執行
server:
port: 8080
spring:
cloud:
gateway:
routes:
- id: neo_route
uri: http://localhost:2001/
predicates:
- Path=/discoveryClient
- Header=X-Request-Id, \d+
使用curl命令測試,可以看到 Header 屬性值和正則表達式匹配的請求可以正確路由,否則會404
C:\Users\mm>curl http://localhost:8080/discoveryClient -H "X-Request-Id:666666"
Services: []
C:\Users\mm>curl http://localhost:8080/discoveryClient -H "X-Request-Id:IO"
{"timestamp":"2020-12-09T07:10:48.753+00:00","path":"/discoveryClient","status":404,"error":"Not Found","message":null,"requestId":"07aaa6b2-2"}
4.通過Host匹配(Host)
Host Route Predicate 接收一組參數,一組匹配的域名列表,這個模板是一個 ant 分隔的模板,用.
號作為分隔符。它通過參數中的主機地址作為匹配規則
server:
port: 8080
spring:
cloud:
gateway:
routes:
- id: neo_route
uri: http://localhost:2001/
predicates:
- Path=/discoveryClient
- Host=**.baidu.com
使用curl命令測試,可以看到 去掉 host 參數或者host參數值和規則不匹配 會報 404 錯誤
C:\Users\mm>curl http://localhost:8080/discoveryClient -H "Host: cn.baidu.com"
Services: []
C:\Users\mm>curl http://localhost:8080/discoveryClient -H "Host: www.baidu.com"
Services: []
C:\Users\mm>curl http://localhost:8080/discoveryClient -H "Host: www.baid.com"
{"timestamp":"2020-12-09T08:08:35.150+00:00","path":"/discoveryClient","status":404,"error":"Not Found","message":null,"requestId":"3e93a018-4"}
C:\Users\mm>curl http://localhost:8080/discoveryClient
{"timestamp":"2020-12-09T08:08:40.223+00:00","path":"/discoveryClient","status":404,"error":"Not Found","message":null,"requestId":"e8d97b0c-5"}
5.通過請求方式匹配(Method)
可以通過是 POST、GET、PUT、DELETE 等不同的請求方式來進行路由
server:
port: 8080
spring:
cloud:
gateway:
routes:
- id: neo_route
uri: http://localhost:2001/
predicates:
- Path=/discoveryClient
- Method=GET
curl 分別測試GET , POST 方法,看效果如下。 curl默認是GET方法
C:\Users\mm>curl http://localhost:8080/discoveryClient
Services: []
C:\Users\mm>curl -X POST http://localhost:8080/discoveryClient
{"timestamp":"2020-12-09T08:13:14.466+00:00","path":"/discoveryClient","status":404,"error":"Not Found","message":null,"requestId":"3cea7707-2"}
6.通過請求路徑匹配(Path)
Path Route Predicate 接收一個匹配路徑的參數來判斷是否走路由,以上的例子都用了Path匹配
7.通過請求參數匹配(QueryParam)
7.1 Query Route Predicate 支持傳入兩個參數,一個是屬性名一個為屬性值,屬性值可以是正則表達式。
server:
port: 8080
spring:
cloud:
gateway:
routes:
- id: neo_route
uri: http://localhost:2001/
predicates:
- Path=/discoveryClient
- Query=smile
重啟網關服務,訪問http://localhost:8080/discoveryClient?smile=x, 可以正確路由到 http://localhost:2001/discoveryClient;訪問http://localhost:8080/discoveryClient?smile=x&id=2, 可以正確路由到 http://localhost:2001/discoveryClient;也就是說只要請求中包含 smile 屬性的參數即可匹配路由。
7.2 將 Query 的值以鍵值對的方式進行配置,這樣在請求過來時會對屬性值和正則進行匹配,匹配上才會走路由
server:
port: 8080
spring:
cloud:
gateway:
routes:
- id: neo_route
uri: http://localhost:2001/
predicates:
- Path=/discoveryClient
- Query=keep, pu.
重啟網關服務,訪問 http://localhost:8080/discoveryClient?keep=pu2,可以正確路由到 http://localhost:2001/discoveryClient;訪問 http://localhost:8080/discoveryClient?keep=pu23 ,返回404。也就是說:只有當請求中包含 keep 屬性並且參數值是以 pu 開頭的長度為三位的字符串才會進行匹配和路由
7.3 匹配多個請求參數
server:
port: 8080
spring:
cloud:
gateway:
routes:
- id: neo_route
uri: http://localhost:2001/
predicates:
- Path=/discoveryClient
- Query=smile
- Query=keep, pu.
重啟網關服務,訪問 http://localhost:8080/discoveryClient?smile=4&keep=pu8,可以正確路由到 http://localhost:2001/discoveryClient
8.通過請求 ip 地址進行匹配(RemoteAddr)
Predicate 也支持通過設置某個 ip 區間號段的請求才會路由,RemoteAddr Route Predicate 接受 cidr 符號(IPv4 或 IPv6 )字符串的列表(最小大小為1),例如 192.168.0.1/16 (其中 192.168.0.1 是 IP 地址,16 是子網掩碼)
如果請求的遠程地址是 192.168.1.10,則此路由將匹配。
server:
port: 8080
spring:
cloud:
gateway:
routes:
- id: neo_route
uri: http://localhost:2001/
predicates:
- Path=/discoveryClient
- RemoteAddr=192.168.1.1/24
可以將此地址設置為本機的 ip 地址進行測試
C:\Users\mm>curl http://localhost:8080/discoveryClient
9.組合Predicate
其實以上例子都用了- Path 和 其它Predicate的組合使用。當各種 Predicates 同時存在於同一個路由時,請求必須同時滿足所有的條件才被這個路由匹配。
server:
port: 8080
spring:
cloud:
gateway:
routes:
- id: neo_route
uri: http://localhost:2001/
predicates:
- Path=/discoveryClient
- Before=2020-12-01T06:06:06+08:00[Asia/Shanghai]
- Cookie=name, mtest
- Query=smile
10.一個請求滿足多個路由的謂詞條件時,請求只會被首個成功匹配的路由轉發