SpringCloud Gateway中斷言路由和過(guò)濾器的使用詳解
一、Gateway概念
Spring Cloud Gateway(簡(jiǎn)稱 Gateway)是一個(gè)基于 Spring WebFlux 的 API 網(wǎng)關(guān)解決方案,旨在為微服務(wù)架構(gòu)中的客戶端提供路由、負(fù)載均衡、認(rèn)證、限流、監(jiān)控等功能。
它作為微服務(wù)架構(gòu)中的流量入口,通常位于客戶端和后端微服務(wù)之間,處理來(lái)自客戶端的請(qǐng)求并將其路由到相應(yīng)的服務(wù)。
主要特性:
- 路由功能:Spring Cloud Gateway 可以根據(jù)請(qǐng)求的不同特征(如路徑、方法、頭部、參數(shù)等)將請(qǐng)求路由到不同的微服務(wù)。
- 負(fù)載均衡:支持與服務(wù)注冊(cè)中心(如 Eureka)集成,能夠?qū)⒘髁糠职l(fā)到多個(gè)實(shí)例,以實(shí)現(xiàn)負(fù)載均衡。
- 過(guò)濾器:提供了豐富的過(guò)濾器功能,可以在請(qǐng)求和響應(yīng)的生命周期中進(jìn)行定制化處理。例如,身份認(rèn)證、日志記錄、限流等。
- 反向代理:可以將請(qǐng)求轉(zhuǎn)發(fā)給后端服務(wù),實(shí)現(xiàn)反向代理功能。
- 高可用和可擴(kuò)展性:通過(guò)與 Spring Cloud 配合使用,Spring Cloud Gateway 能夠在微服務(wù)架構(gòu)中提供高可用和擴(kuò)展性支持。
- 監(jiān)控:可以與 Spring Boot Actuator 集成,提供請(qǐng)求和響應(yīng)的監(jiān)控功能,幫助開發(fā)人員監(jiān)控系統(tǒng)的健康狀況和性能。
二、基本路由
路由是將客戶端請(qǐng)求發(fā)送到后端服務(wù)的主要組件。它定義了請(qǐng)求的匹配規(guī)則以及請(qǐng)求將被轉(zhuǎn)發(fā)到的目標(biāo)(即URI)。每個(gè)路由都具有一個(gè)id
、uri
以及predicates
。
id
:每個(gè)路由的唯一標(biāo)識(shí)符。uri
:路由轉(zhuǎn)發(fā)的目標(biāo)URI。對(duì)于lb://
協(xié)議,它指向服務(wù)注冊(cè)中心(如Eureka)中的服務(wù),表示請(qǐng)求將被轉(zhuǎn)發(fā)到注冊(cè)的服務(wù)。predicates
:定義了路由的匹配條件,決定哪些請(qǐng)求將被此路由處理。
spring: cloud: gateway: routes: - id: order-route uri: lb://service-order predicates: - Path=/api/order/**
三、斷言
斷言(Predicates) 用于根據(jù)請(qǐng)求的各種屬性來(lái)匹配路由,它們是路由的核心部分。
斷言支持不同的匹配條件,如路徑、請(qǐng)求方法、請(qǐng)求頭等。通過(guò)不同的請(qǐng)求模式來(lái)匹配對(duì)應(yīng)的微服務(wù)。
3.1在Spring Cloud Gateway的配置中,斷言有兩種寫法
- 長(zhǎng)寫法:指定完整的斷言語(yǔ)法,明確標(biāo)明斷言的類型。
spring: cloud: gateway: routes: - id: order-route uri: lb://service-order predicates: - name: Path args: pattern: /api/order/**
- 短寫法:是斷言的簡(jiǎn)化寫法,直接使用斷言類型的簡(jiǎn)潔形式。
spring: cloud: gateway: routes: - id: order-route uri: lb://service-order predicates: - Path=/api/order/**
系統(tǒng)內(nèi)置斷言(Predicates)
Spring Cloud Gateway 提供了很多內(nèi)置的斷言類型,用來(lái)處理各種請(qǐng)求匹配需求。常用的斷言類型包括:
這張圖展示了Spring Cloud Gateway中常用的路由斷言(Predicates)及其相關(guān)參數(shù)說(shuō)明。斷言是路由配置的重要組成部分,它們用來(lái)判斷請(qǐng)求是否滿足特定條件,以決定是否將請(qǐng)求轉(zhuǎn)發(fā)到目標(biāo)服務(wù)。
每種斷言都允許通過(guò)指定參數(shù)來(lái)對(duì)請(qǐng)求進(jìn)行詳細(xì)匹配。
3.2自定義斷言
我們通過(guò)繼承 AbstractRoutePredicateFactory
類,創(chuàng)建了一個(gè)名為 VipRoutePredicateFactory
的類,實(shí)現(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) { // 獲取請(qǐng)求 ServerHttpRequest request = serverWebExchange.getRequest(); // 從請(qǐng)求的查詢參數(shù)中獲取 'param' 對(duì)應(yīng)的值 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
,實(shí)現(xiàn)了自定義斷言工廠的功能。 AbstractRoutePredicateFactory
是 Spring Cloud Gateway 提供的基礎(chǔ)類,用于創(chuàng)建自定義的路由斷言。- 我們將
Config.class
作為構(gòu)造函數(shù)的參數(shù)傳遞給父類,表示我們會(huì)用Config
類來(lái)存儲(chǔ)斷言所需的配置參數(shù)。
shortcutFieldOrder()
方法
- 這個(gè)方法返回一個(gè)
List<String>
,用于定義配置類中字段的順序。 - 在這個(gè)例子中,
param
和value
的順序決定了用戶在配置時(shí),param
和value
應(yīng)該以這個(gè)順序出現(xiàn)。 - Spring Cloud Gateway 使用
shortcutFieldOrder()
方法來(lái)生成簡(jiǎn)潔的 YAML 配置。
spring: cloud: gateway: routes: - id: vip-route uri: https://example.com predicates: - name: Vip(RoutePredicateFactory)//vip是斷言工廠名前綴 args: param: q value: test
apply(Config config)
方法
- 這個(gè)方法用于應(yīng)用自定義斷言的邏輯,接收
Config
類的實(shí)例作為參數(shù)。 Config
類包含了路由斷言所需的參數(shù)(param
和value
)。- 該方法返回一個(gè)
Predicate<ServerWebExchange>
,用于對(duì)每個(gè)請(qǐng)求進(jìn)行斷言判斷。
這里的 Predicate<ServerWebExchange>
表示一個(gè)函數(shù),它接收一個(gè) ServerWebExchange
(表示當(dāng)前請(qǐng)求),并返回一個(gè)布爾值,表示該請(qǐng)求是否匹配該斷言。
test(ServerWebExchange serverWebExchange)
方法
- 在這個(gè)方法中,我們實(shí)際執(zhí)行請(qǐng)求的匹配邏輯。首先通過(guò)
serverWebExchange.getRequest()
獲取當(dāng)前請(qǐng)求對(duì)象。接著,我們從請(qǐng)求的查詢參數(shù)中獲取與config.param
對(duì)應(yīng)的值,存儲(chǔ)在first
變量中。 - 然后,我們檢查
first
是否為空,并與config.value
進(jìn)行比較。如果它們相等,并且查詢參數(shù)不為空,我們返回true
,表示路由匹配成功;否則返回false
,表示路由不匹配。
Config
類
Config
類是一個(gè)靜態(tài)類,用來(lái)存儲(chǔ)自定義斷言需要的配置參數(shù)。這里有兩個(gè)字段:param
表示查詢參數(shù)的名稱,value
表示查詢參數(shù)的期望值。用戶通過(guò)配置文件傳入這兩個(gè)參數(shù)。Config
類的作用是封裝從配置文件中讀取的參數(shù),并通過(guò)@Validated
等注解進(jìn)行驗(yàn)證
四、過(guò)濾器
過(guò)濾器(Filters) 是用于在請(qǐng)求和響應(yīng)過(guò)程中執(zhí)行特定操作的機(jī)制。它們是在路由決策之前或之后執(zhí)行的,可以對(duì)請(qǐng)求進(jìn)行修改(如添加頭部、修改請(qǐng)求體)或響應(yīng)進(jìn)行處理(如修改響應(yīng)內(nèi)容、記錄日志等)。
過(guò)濾器的使用大致可以分為兩種類型:前置過(guò)濾器(pre-filter)和后置過(guò)濾器(post-filter)。前置過(guò)濾器在請(qǐng)求到達(dá)目標(biāo)服務(wù)之前執(zhí)行,后置過(guò)濾器則在響應(yīng)返回客戶端之前執(zhí)行。
過(guò)濾器主要用于以下目的:
- 請(qǐng)求和響應(yīng)的修改。
- 安全性(如身份驗(yàn)證)。
- 負(fù)載均衡和限流。
- 請(qǐng)求日志和性能監(jiān)控。
4.1基本的過(guò)濾器使用步驟
添加依賴: 需要在pom.xml
文件中加入Spring Cloud Gateway的依賴:
<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
創(chuàng)建過(guò)濾器: 可以通過(guò)實(shí)現(xiàn)GatewayFilter
接口來(lái)創(chuàng)建自定義過(guò)濾器。Spring Cloud Gateway提供了GatewayFilter
接口和GlobalFilter
接口,分別用于處理特定路由和全局的請(qǐng)求過(guò)濾。
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) { // 在請(qǐng)求處理之前執(zhí)行的邏輯 System.out.println("請(qǐng)求被過(guò)濾: " + exchange.getRequest().getURI()); // 執(zhí)行后續(xù)過(guò)濾器鏈 return chain.filter(exchange); } }
注冊(cè)過(guò)濾器: 自定義過(guò)濾器可以通過(guò)注入GatewayFilter
的方式注冊(cè)到Spring的上下文中??梢詫⑦^(guò)濾器注入到@Configuration
中,或者直接使用@Component
注解讓其自動(dòng)注冊(cè)。
配置路由過(guò)濾器: 在路由配置中,可以為某個(gè)特定的路由設(shè)置過(guò)濾器。
spring: cloud: gateway: routes: - id: my_route uri: http://httpbin.org:80 predicates: - Path=/get filters: - name: RequestHeaderToRequestUri args: name: X-Request-Id
4.2全局過(guò)濾器使用步驟
全局過(guò)濾器是應(yīng)用于所有路由請(qǐng)求的過(guò)濾器,它們?cè)谡?qǐng)求到達(dá)目標(biāo)服務(wù)之前和響應(yīng)返回時(shí)都會(huì)被執(zhí)行。全局過(guò)濾器對(duì)于記錄日志、身份驗(yàn)證等場(chǎng)景非常有用。
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) { // 記錄請(qǐng)求的URL String path = exchange.getRequest().getURI().getPath(); System.out.println("Request Path: " + path); // 繼續(xù)處理鏈中的下一個(gè)過(guò)濾器 return chain.filter(exchange); } }
4.3自定義過(guò)濾器使用步驟
Spring Cloud Gateway允許開發(fā)者創(chuàng)建自定義過(guò)濾器。
自定義過(guò)濾器有兩種類型:
GatewayFilter
:只能作用于單個(gè)路由。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) { // 獲取請(qǐng)求的路徑 String path = exchange.getRequest().getURI().getPath(); // 記錄請(qǐng)求的路徑 System.out.println("Request Path: " + path); // 向請(qǐng)求中添加一個(gè)自定義的請(qǐng)求頭 exchange.getRequest().mutate() .header("X-Request-ID", "Request-" + System.currentTimeMillis()) // 設(shè)置一個(gè)自定義請(qǐng)求頭 .build(); // 繼續(xù)處理請(qǐng)求 return chain.filter(exchange) .doOnTerminate(() -> { // 記錄響應(yīng)結(jié)束時(shí)的日志 System.out.println("Request " + path + " processed."); }); } }
LoggingGlobalFilter
實(shí)現(xiàn)了 GlobalFilter
接口:
該過(guò)濾器會(huì)應(yīng)用于所有的請(qǐng)求,不管是哪個(gè)路由請(qǐng)求都會(huì)執(zhí)行這個(gè)過(guò)濾器的邏輯。
filter()
方法:
- 在這個(gè)方法中,首先我們通過(guò)
exchange.getRequest().getURI().getPath()
獲取當(dāng)前請(qǐng)求的路徑。 - 然后,我們通過(guò)
System.out.println()
打印日志,記錄下請(qǐng)求的路徑。 - 接著,我們使用
mutate()
方法修改請(qǐng)求,添加了一個(gè)自定義的請(qǐng)求頭X-Request-ID
,其值為當(dāng)前時(shí)間戳(這樣可以在日志中唯一標(biāo)識(shí)每個(gè)請(qǐng)求)。 - 最后,通過(guò)
chain.filter(exchange)
將請(qǐng)求繼續(xù)傳遞給下一個(gè)過(guò)濾器鏈
4.4過(guò)濾器的執(zhí)行順序
Spring Cloud Gateway的過(guò)濾器按以下順序執(zhí)行:
- 請(qǐng)求過(guò)濾器:請(qǐng)求從客戶端進(jìn)入網(wǎng)關(guān)后,過(guò)濾器鏈會(huì)逐個(gè)執(zhí)行請(qǐng)求過(guò)濾器。
- 過(guò)濾器執(zhí)行順序是鏈?zhǔn)降模?code>GlobalFilter ->
GatewayFilter
- 過(guò)濾器執(zhí)行順序是鏈?zhǔn)降模?code>GlobalFilter ->
- 響應(yīng)過(guò)濾器:請(qǐng)求被轉(zhuǎn)發(fā)到目標(biāo)服務(wù),響應(yīng)返回時(shí),再次按鏈?zhǔn)綀?zhí)行響應(yīng)過(guò)濾器。
4.5常用過(guò)濾器
Spring Cloud Gateway提供了一些內(nèi)置的過(guò)濾器,可以直接使用。例如:
AddRequestHeader
:添加請(qǐng)求頭部。AddResponseHeader
:添加響應(yīng)頭部。RemoveRequestHeader
:刪除請(qǐng)求頭部。RemoveResponseHeader
:刪除響應(yīng)頭部。SetPath
:修改請(qǐng)求路徑。RewritePath
:重寫路徑。
添加請(qǐng)求頭的過(guò)濾器舉例:
spring: cloud: gateway: routes: - id: add-header-route uri: http://localhost:8081 predicates: - Path=/add-header/** filters: - AddRequestHeader=X-Custom-Header, Value
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
java學(xué)生信息管理系統(tǒng)MVC架構(gòu)詳解
這篇文章主要為大家詳細(xì)介紹了java學(xué)生信息管理系統(tǒng)MVC架構(gòu)的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-11-11SpringCloud之動(dòng)態(tài)刷新、重試、服務(wù)化的實(shí)現(xiàn)
這篇文章主要介紹了SpringCloud 之動(dòng)態(tài)刷新、重試、服務(wù)化的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10并發(fā)編程之Java內(nèi)存模型鎖的內(nèi)存語(yǔ)義
這篇文章主要介紹了并發(fā)編程之Java內(nèi)存模型鎖的內(nèi)存語(yǔ)義,鎖的作用是讓臨界區(qū)互斥執(zhí)行,本文只要圍繞鎖的內(nèi)存語(yǔ)義展開全文內(nèi)容,需要的小伙伴可以參考一下2021-11-11Java手把手必會(huì)的實(shí)例漢諾塔講解練習(xí)
漢諾塔,傳說(shuō)神在創(chuàng)造世界的時(shí)候做了三根金剛石柱子,并在一個(gè)教塔里留下了三根金剛石棒,第一根上面從上到下套著64個(gè)按從小到大排列的金盤,神命令廟里的眾僧將它們一個(gè)個(gè)地從這根金剛石棒搬到另一根金剛石棒上,大盤不能放在小盤上。最后64個(gè)金盤仍然要按從小到大排列2021-09-09Java實(shí)現(xiàn)向Word文檔添加文檔屬性
這篇文章主要介紹了Java實(shí)現(xiàn)向Word文檔添加文檔屬性的相關(guān)資料,需要的朋友可以參考下2023-01-01