SpringCloud Gateway中斷言路由和過濾器的使用詳解
一、Gateway概念
Spring Cloud Gateway(簡稱 Gateway)是一個基于 Spring WebFlux 的 API 網關解決方案,旨在為微服務架構中的客戶端提供路由、負載均衡、認證、限流、監(jiān)控等功能。
它作為微服務架構中的流量入口,通常位于客戶端和后端微服務之間,處理來自客戶端的請求并將其路由到相應的服務。
主要特性:
- 路由功能:Spring Cloud Gateway 可以根據(jù)請求的不同特征(如路徑、方法、頭部、參數(shù)等)將請求路由到不同的微服務。
- 負載均衡:支持與服務注冊中心(如 Eureka)集成,能夠將流量分發(fā)到多個實例,以實現(xiàn)負載均衡。
- 過濾器:提供了豐富的過濾器功能,可以在請求和響應的生命周期中進行定制化處理。例如,身份認證、日志記錄、限流等。
- 反向代理:可以將請求轉發(fā)給后端服務,實現(xiàn)反向代理功能。
- 高可用和可擴展性:通過與 Spring Cloud 配合使用,Spring Cloud Gateway 能夠在微服務架構中提供高可用和擴展性支持。
- 監(jiān)控:可以與 Spring Boot Actuator 集成,提供請求和響應的監(jiān)控功能,幫助開發(fā)人員監(jiān)控系統(tǒng)的健康狀況和性能。
二、基本路由
路由是將客戶端請求發(fā)送到后端服務的主要組件。它定義了請求的匹配規(guī)則以及請求將被轉發(fā)到的目標(即URI)。每個路由都具有一個id、uri以及predicates。
id:每個路由的唯一標識符。uri:路由轉發(fā)的目標URI。對于lb://協(xié)議,它指向服務注冊中心(如Eureka)中的服務,表示請求將被轉發(fā)到注冊的服務。predicates:定義了路由的匹配條件,決定哪些請求將被此路由處理。
spring:
cloud:
gateway:
routes:
- id: order-route
uri: lb://service-order
predicates:
- Path=/api/order/**三、斷言
斷言(Predicates) 用于根據(jù)請求的各種屬性來匹配路由,它們是路由的核心部分。
斷言支持不同的匹配條件,如路徑、請求方法、請求頭等。通過不同的請求模式來匹配對應的微服務。
3.1在Spring Cloud Gateway的配置中,斷言有兩種寫法
- 長寫法:指定完整的斷言語法,明確標明斷言的類型。
spring:
cloud:
gateway:
routes:
- id: order-route
uri: lb://service-order
predicates:
- name: Path
args:
pattern: /api/order/**- 短寫法:是斷言的簡化寫法,直接使用斷言類型的簡潔形式。
spring:
cloud:
gateway:
routes:
- id: order-route
uri: lb://service-order
predicates:
- Path=/api/order/**系統(tǒng)內置斷言(Predicates)
Spring Cloud Gateway 提供了很多內置的斷言類型,用來處理各種請求匹配需求。常用的斷言類型包括:

這張圖展示了Spring Cloud Gateway中常用的路由斷言(Predicates)及其相關參數(shù)說明。斷言是路由配置的重要組成部分,它們用來判斷請求是否滿足特定條件,以決定是否將請求轉發(fā)到目標服務。
每種斷言都允許通過指定參數(shù)來對請求進行詳細匹配。
3.2自定義斷言
我們通過繼承 AbstractRoutePredicateFactory 類,創(chuàng)建了一個名為 VipRoutePredicateFactory 的類,實現(xiàn)了自定義的路由斷言邏輯,示例代碼如下:
import org.springframework.cloud.gateway.handler.predicate.AbstractRoutePredicateFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.apache.commons.lang3.StringUtils;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
/**
* 自定義路由斷言工廠
*/
@Component
public class VipRoutePredicateFactory extends AbstractRoutePredicateFactory<VipRoutePredicateFactory.Config> {
public VipRoutePredicateFactory() {
super(Config.class); // 傳入Config類
}
@Override
public List<String> shortcutFieldOrder() {
// 返回配置類中的字段順序
return Arrays.asList("param", "value");
}
@Override
public Predicate<ServerWebExchange> apply(Config config) {
return new GatewayPredicate() {
@Override
public boolean test(ServerWebExchange serverWebExchange) {
// 獲取請求
ServerHttpRequest request = serverWebExchange.getRequest();
// 從請求的查詢參數(shù)中獲取 'param' 對應的值
String first = request.getQueryParams().getFirst(config.param);
// 比較查詢參數(shù)的值與配置中的 'value' 是否匹配
return StringUtils.isNotBlank(first) && first.equals(config.value);
}
};
}
// 配置類
public static class Config {
private String param; // 查詢參數(shù)名稱
private String value; // 查詢參數(shù)期望的值
// Getter和Setter方法
public String getParam() {
return param;
}
public void setParam(String param) {
this.param = param;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
}VipRoutePredicateFactory 類
- 該類繼承自
AbstractRoutePredicateFactory,實現(xiàn)了自定義斷言工廠的功能。 AbstractRoutePredicateFactory是 Spring Cloud Gateway 提供的基礎類,用于創(chuàng)建自定義的路由斷言。- 我們將
Config.class作為構造函數(shù)的參數(shù)傳遞給父類,表示我們會用Config類來存儲斷言所需的配置參數(shù)。
shortcutFieldOrder() 方法
- 這個方法返回一個
List<String>,用于定義配置類中字段的順序。 - 在這個例子中,
param和value的順序決定了用戶在配置時,param和value應該以這個順序出現(xiàn)。 - Spring Cloud Gateway 使用
shortcutFieldOrder()方法來生成簡潔的 YAML 配置。
spring:
cloud:
gateway:
routes:
- id: vip-route
uri: https://example.com
predicates:
- name: Vip(RoutePredicateFactory)//vip是斷言工廠名前綴
args:
param: q
value: testapply(Config config) 方法
- 這個方法用于應用自定義斷言的邏輯,接收
Config類的實例作為參數(shù)。 Config類包含了路由斷言所需的參數(shù)(param和value)。- 該方法返回一個
Predicate<ServerWebExchange>,用于對每個請求進行斷言判斷。
這里的 Predicate<ServerWebExchange> 表示一個函數(shù),它接收一個 ServerWebExchange(表示當前請求),并返回一個布爾值,表示該請求是否匹配該斷言。
test(ServerWebExchange serverWebExchange) 方法
- 在這個方法中,我們實際執(zhí)行請求的匹配邏輯。首先通過
serverWebExchange.getRequest()獲取當前請求對象。接著,我們從請求的查詢參數(shù)中獲取與config.param對應的值,存儲在first變量中。 - 然后,我們檢查
first是否為空,并與config.value進行比較。如果它們相等,并且查詢參數(shù)不為空,我們返回true,表示路由匹配成功;否則返回false,表示路由不匹配。
Config 類
Config類是一個靜態(tài)類,用來存儲自定義斷言需要的配置參數(shù)。這里有兩個字段:param表示查詢參數(shù)的名稱,value表示查詢參數(shù)的期望值。用戶通過配置文件傳入這兩個參數(shù)。Config類的作用是封裝從配置文件中讀取的參數(shù),并通過@Validated等注解進行驗證
四、過濾器
過濾器(Filters) 是用于在請求和響應過程中執(zhí)行特定操作的機制。它們是在路由決策之前或之后執(zhí)行的,可以對請求進行修改(如添加頭部、修改請求體)或響應進行處理(如修改響應內容、記錄日志等)。
過濾器的使用大致可以分為兩種類型:前置過濾器(pre-filter)和后置過濾器(post-filter)。前置過濾器在請求到達目標服務之前執(zhí)行,后置過濾器則在響應返回客戶端之前執(zhí)行。
過濾器主要用于以下目的:
- 請求和響應的修改。
- 安全性(如身份驗證)。
- 負載均衡和限流。
- 請求日志和性能監(jiān)控。
4.1基本的過濾器使用步驟
添加依賴: 需要在pom.xml文件中加入Spring Cloud Gateway的依賴:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>創(chuàng)建過濾器: 可以通過實現(xiàn)GatewayFilter接口來創(chuàng)建自定義過濾器。Spring Cloud Gateway提供了GatewayFilter接口和GlobalFilter接口,分別用于處理特定路由和全局的請求過濾。
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class MyCustomFilter implements GatewayFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 在請求處理之前執(zhí)行的邏輯
System.out.println("請求被過濾: " + exchange.getRequest().getURI());
// 執(zhí)行后續(xù)過濾器鏈
return chain.filter(exchange);
}
}注冊過濾器: 自定義過濾器可以通過注入GatewayFilter的方式注冊到Spring的上下文中??梢詫⑦^濾器注入到@Configuration中,或者直接使用@Component注解讓其自動注冊。
配置路由過濾器: 在路由配置中,可以為某個特定的路由設置過濾器。
spring:
cloud:
gateway:
routes:
- id: my_route
uri: http://httpbin.org:80
predicates:
- Path=/get
filters:
- name: RequestHeaderToRequestUri
args:
name: X-Request-Id4.2全局過濾器使用步驟
全局過濾器是應用于所有路由請求的過濾器,它們在請求到達目標服務之前和響應返回時都會被執(zhí)行。全局過濾器對于記錄日志、身份驗證等場景非常有用。
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
@Component
public class LoggingGlobalFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 記錄請求的URL
String path = exchange.getRequest().getURI().getPath();
System.out.println("Request Path: " + path);
// 繼續(xù)處理鏈中的下一個過濾器
return chain.filter(exchange);
}
}4.3自定義過濾器使用步驟
Spring Cloud Gateway允許開發(fā)者創(chuàng)建自定義過濾器。
自定義過濾器有兩種類型:
GatewayFilter:只能作用于單個路由。GlobalFilter:作用于所有路由。
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.http.HttpStatus;
import reactor.core.publisher.Mono;
@Component
public class LoggingGlobalFilter implements GlobalFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
// 獲取請求的路徑
String path = exchange.getRequest().getURI().getPath();
// 記錄請求的路徑
System.out.println("Request Path: " + path);
// 向請求中添加一個自定義的請求頭
exchange.getRequest().mutate()
.header("X-Request-ID", "Request-" + System.currentTimeMillis()) // 設置一個自定義請求頭
.build();
// 繼續(xù)處理請求
return chain.filter(exchange)
.doOnTerminate(() -> {
// 記錄響應結束時的日志
System.out.println("Request " + path + " processed.");
});
}
}LoggingGlobalFilter 實現(xiàn)了 GlobalFilter 接口:
該過濾器會應用于所有的請求,不管是哪個路由請求都會執(zhí)行這個過濾器的邏輯。
filter() 方法:
- 在這個方法中,首先我們通過
exchange.getRequest().getURI().getPath()獲取當前請求的路徑。 - 然后,我們通過
System.out.println()打印日志,記錄下請求的路徑。 - 接著,我們使用
mutate()方法修改請求,添加了一個自定義的請求頭X-Request-ID,其值為當前時間戳(這樣可以在日志中唯一標識每個請求)。 - 最后,通過
chain.filter(exchange)將請求繼續(xù)傳遞給下一個過濾器鏈
4.4過濾器的執(zhí)行順序
Spring Cloud Gateway的過濾器按以下順序執(zhí)行:
- 請求過濾器:請求從客戶端進入網關后,過濾器鏈會逐個執(zhí)行請求過濾器。
- 過濾器執(zhí)行順序是鏈式的:
GlobalFilter->GatewayFilter
- 過濾器執(zhí)行順序是鏈式的:
- 響應過濾器:請求被轉發(fā)到目標服務,響應返回時,再次按鏈式執(zhí)行響應過濾器。
4.5常用過濾器
Spring Cloud Gateway提供了一些內置的過濾器,可以直接使用。例如:
AddRequestHeader:添加請求頭部。AddResponseHeader:添加響應頭部。RemoveRequestHeader:刪除請求頭部。RemoveResponseHeader:刪除響應頭部。SetPath:修改請求路徑。RewritePath:重寫路徑。
添加請求頭的過濾器舉例:
spring:
cloud:
gateway:
routes:
- id: add-header-route
uri: http://localhost:8081
predicates:
- Path=/add-header/**
filters:
- AddRequestHeader=X-Custom-Header, Value總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Executor攔截器高級教程QueryInterceptor的規(guī)范
今天小編就為大家分享一篇關于Executor攔截器高級教程QueryInterceptor的規(guī)范,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-12-12
spring boot創(chuàng)建和數(shù)據(jù)庫關聯(lián)模塊詳解
這篇文章主要給大家介紹了關于spring boot創(chuàng)建和數(shù)據(jù)庫關聯(lián)模塊的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-10-10
Springboot與Maven多環(huán)境配置的解決方案
多環(huán)境配置的解決方案有很多,我看到不少項目的多環(huán)境配置都是使用Maven來實現(xiàn)的,本文就實現(xiàn)Springboot與Maven多環(huán)境配置,感興趣的可以了解下2021-06-06
SpringMVC日期類型參數(shù)傳遞實現(xiàn)步驟講解
這篇文章主要介紹了SpringMVC日期類型參數(shù)傳遞實現(xiàn)步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧2023-02-02
Springboot2 session設置超時時間無效的解決
這篇文章主要介紹了Springboot2 session設置超時時間無效的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-07-07
java小知識之查詢數(shù)據(jù)庫數(shù)據(jù)的元信息
這篇文章主要給大家介紹了關于java小知識之查詢數(shù)據(jù)庫數(shù)據(jù)的元信息,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下2021-10-10

