springboot使用Gateway做網(wǎng)關(guān)并且配置全局?jǐn)r截器的方式
一、為什么要用網(wǎng)關(guān)
統(tǒng)一入口:
- 作用:作為所有客戶端請求的統(tǒng)一入口。
- 說明:所有客戶端請求都通過網(wǎng)關(guān)進(jìn)行路由,網(wǎng)關(guān)負(fù)責(zé)將請求轉(zhuǎn)發(fā)到后端的微服務(wù)
路由轉(zhuǎn)發(fā):
- 作用:根據(jù)請求的URL、方法等信息將請求路由到不同的微服務(wù)。
- 說明:網(wǎng)關(guān)可以根據(jù)配置的路由規(guī)則,將請求轉(zhuǎn)發(fā)到正確的微服務(wù),實(shí)現(xiàn)請求的路由和負(fù)載均衡。
負(fù)載均衡:
- 作用:實(shí)現(xiàn)請求的負(fù)載均衡。
- 說明:網(wǎng)關(guān)可以集成負(fù)載均衡組件(如Ribbon),根據(jù)負(fù)載均衡策略將請求分發(fā)到不同的服務(wù)實(shí)例,提高系統(tǒng)的可用性和擴(kuò)展性。
服務(wù)發(fā)現(xiàn):
- 作用:與服務(wù)注冊中心集成,實(shí)現(xiàn)服務(wù)的自動發(fā)現(xiàn)。
- 說明:網(wǎng)關(guān)可以與Eureka等服務(wù)注冊中心集成,動態(tài)獲取服務(wù)實(shí)例的信息,實(shí)現(xiàn)服務(wù)的自動發(fā)現(xiàn)和路由。
認(rèn)證與授權(quán):
- 作用:提供統(tǒng)一的安全認(rèn)證和授權(quán)機(jī)制。
- 說明:網(wǎng)關(guān)可以集成認(rèn)證和授權(quán)組件(如OAuth2、JWT),對所有進(jìn)入的請求進(jìn)行安全檢查,確保只有合法的請求才能訪問后端服務(wù)。
跨域資源共享(CORS):
- 作用:處理跨域請求。
- 說明:網(wǎng)關(guān)可以處理跨域請求,允許來自不同域的客戶端訪問后端服務(wù),解決了瀏覽器的同源策略限制。
二、Gateway簡單使用
第一步:引入Gateway的maven依賴到pom.xml文件
<dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
第二步:編寫配置文件application.yml文件,如下所示:
server: port: 10086 # 網(wǎng)關(guān)端口 spring: application: name: gateway # 服務(wù)名稱 cloud: nacos: server-addr: localhost:8848 # nacos 地址 gateway: routes: # 網(wǎng)關(guān)路由配置 - id: provider # 路由id,自定義,只要唯一即可 # uri: http://127.0.0.1:8081 # 路由的目標(biāo)地址 (直接寫死地址的方式,不推薦) uri: lb://provider # 路由的目標(biāo)地址 lb是負(fù)載均衡,后面跟服務(wù)名稱(推薦) predicates: # 路由斷言,判斷請求是否符合路由規(guī)則的條件 - Path=/provider/** # 按照路徑匹配,以/user/開頭的請求就符合要求
第三步:啟動測試
當(dāng)然要注意的是我們需要開啟另一個服務(wù)provider服務(wù),并且這個服務(wù)需要配置方法前綴/provider,當(dāng)我們通過網(wǎng)關(guān)訪問的時候就可以直接的訪問到provider服務(wù)了。
三、Gateway斷言工廠
路由斷言主要用來判斷路由的規(guī)則。
配置文件中寫的斷言規(guī)則只是字符串,這些字符串會被Predicate Factory
讀取并處理。
例如Path=/user/**
是按照路徑匹配,這個規(guī)則是由org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory
類來處理。
像這樣的斷言工廠在SpringCloudGateway還有十幾個:
當(dāng)然這個地方可能給的不是很全所以我貼出官網(wǎng)地址:大家需要的可以去看官網(wǎng):Spring Cloud Gateway
簡單示例,下面我配置一個在訪問之前需要到一定的時間才可以訪問,并且看一下效果
server: port: 10086 # 網(wǎng)關(guān)端口 spring: application: name: gateway # 服務(wù)名稱 cloud: nacos: server-addr: localhost:8848 # nacos 地址 gateway: routes: # 網(wǎng)關(guān)路由配置 - id: provider # 路由id,自定義,只要唯一即可 # uri: http://127.0.0.1:8081 # 路由的目標(biāo)地址 (直接寫死地址的方式,不推薦) uri: lb://provider # 路由的目標(biāo)地址 lb是負(fù)載均衡,后面跟服務(wù)名稱(推薦) predicates: # 路由斷言,判斷請求是否符合路由規(guī)則的條件 - Path=/provider/** # 按照路徑匹配,以/user/開頭的請求就符合要求 - After=2031-01-20T17:42:47.789-07:00[America/Denver]
因為我配置了需要在2031年1月20號后才可以訪問明顯現(xiàn)在是2024年不可以訪問到,所以會報錯404。
四、Gateway路由過濾器
客戶端請求先找到路由,路由匹配時經(jīng)過過濾器層層篩選,最終訪問到微服務(wù)。
當(dāng)然微服務(wù)的請求反悔時,也會經(jīng)過過濾器的篩選,只不過我們一般只對請求過濾,而不會對響應(yīng)過濾。
SpringCloudGateWay目前已經(jīng)提供了34種不同的過濾器工廠。感興趣的大家也可以去上面給出的官網(wǎng)地址查看。
下面我在路由過濾器中添加一個請求頭,并且需要在provider請求中加入一個參數(shù)去拿到請求頭中的參數(shù)
server: port: 10086 # 網(wǎng)關(guān)端口 spring: application: name: gateway # 服務(wù)名稱 cloud: nacos: server-addr: localhost:8848 # nacos 地址 gateway: routes: # 網(wǎng)關(guān)路由配置 - id: provider # 路由id,自定義,只要唯一即可 # uri: http://127.0.0.1:8081 # 路由的目標(biāo)地址 (直接寫死地址的方式,不推薦) uri: lb://provider # 路由的目標(biāo)地址 lb是負(fù)載均衡,后面跟服務(wù)名稱(推薦) predicates: # 路由斷言,判斷請求是否符合路由規(guī)則的條件 - Path=/provider/** # 按照路徑匹配,以/user/開頭的請求就符合要求 filters: # 過濾器配置 - AddRequestHeader=token, test # 添加請求頭
provider請求變?yōu)?,需要拿到請求頭中的信息
@GetMapping("/provider/t") public String t(@RequestHeader(value = "token",required = false)String token){ return "恭喜您測試成功啦!"+token; }
測試
當(dāng)然這是局部配置我們也可以針對所有的路由進(jìn)行全局配置(但是這個配置是需要和路由s是同級的),如下所示:
server: port: 10086 # 網(wǎng)關(guān)端口 spring: application: name: gateway # 服務(wù)名稱 cloud: nacos: server-addr: localhost:8848 # nacos 地址 gateway: routes: # 網(wǎng)關(guān)路由配置 - id: provider # 路由id,自定義,只要唯一即可 # uri: http://127.0.0.1:8081 # 路由的目標(biāo)地址 (直接寫死地址的方式,不推薦) uri: lb://provider # 路由的目標(biāo)地址 lb是負(fù)載均衡,后面跟服務(wù)名稱(推薦) predicates: # 路由斷言,判斷請求是否符合路由規(guī)則的條件 - Path=/provider/** # 按照路徑匹配,以/user/開頭的請求就符合要求 default-filters: # 默認(rèn)過濾器配置 - AddRequestHeader=token, test # 添加請求頭
五、Gateway全局過濾器
上面的gateway路由器可以配置全局的,為什么還需要有一個全局過濾器呢,因為上面的過濾器都是只可以針對與一些邏輯的攔截,但是不可以涉及到一些業(yè)務(wù)的處理,所以就有這個全局過濾器可以通過編寫代碼的方式來編寫業(yè)務(wù)邏輯進(jìn)行對用戶訪問的鑒權(quán)放行等等。
package com.example.demo.filter; import org.springframework.cloud.gateway.filter.GatewayFilterChain; import org.springframework.cloud.gateway.filter.GlobalFilter; import org.springframework.core.Ordered; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import org.springframework.util.MultiValueMap; import org.springframework.web.server.ServerWebExchange; import reactor.core.publisher.Mono; @Component public class GateWayFilter implements GlobalFilter, Ordered { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { // 1.獲取請求參數(shù) //1.這里的request并不是servlet中的request //2.返回值是一個多鍵的map集合、也就是說這個map集合的鍵可以重復(fù) MultiValueMap<String, String> params = exchange.getRequest().getQueryParams(); // 2.獲取userName參數(shù) String userName = params.getFirst("userName"); // 3.校驗 if ("root".equals(userName)) { // 放行 return chain.filter(exchange); } // 4.攔截 // 4.1.禁止訪問,設(shè)置狀態(tài)碼 exchange.getResponse().setStatusCode(HttpStatus.valueOf(500)); // 4.2.結(jié)束處理 return exchange.getResponse().setComplete(); } //過濾器優(yōu)先級,數(shù)字越小優(yōu)先級越高 @Override public int getOrder() { return -1; } }
測試:
我們先正常的訪問之前的請求,會發(fā)現(xiàn)無法使用此頁面也就是被拒絕訪問了
當(dāng)我們加上一個參數(shù)后把userName=root加上之后就可以正確的訪問到請求了
過濾器鏈執(zhí)行順序
SpringCloudGateWay中,有三種過濾器:
- 默認(rèn)過濾器default-filters
- 只對具體某個路由生效的局部過濾器filters
- 使用java代碼編寫的全局過濾器GlobalFilter
過濾器最終都會轉(zhuǎn)化成GlobalFilter(使用的是適配器模式)所以我們就可以把這三種過濾器看成一個整體而順序也入下圖顯示的一致。
由上圖知過濾器的執(zhí)行順序為:默認(rèn)過濾器 → 當(dāng)前路由過濾器 → 全局過濾器。
六、Gateway跨域請求配置
1.跨域請求定義
跨域:請求位置和被請求位置不同源就會發(fā)生跨域。
這里的不同源包括兩個點(diǎn):
- 域名不同:www.baidu.com 和 www.taobao.com。(IP不同也是相同道理)
- 端口不同:127.0.0.1:8080和127.0.0.1:8081。
而瀏覽器又會禁止請求的發(fā)起者與服務(wù)端發(fā)生跨域AJAX請求。
如果發(fā)生了跨域請求,服務(wù)器端是能夠正常響應(yīng)的,但是響應(yīng)的結(jié)果會被瀏覽器攔截。
2.跨域常見解決方案
使用CORS方式。
CORS是一個W3C標(biāo)準(zhǔn),全稱是"跨域資源共享"(Cross-origin resource sharing)。
它允許瀏覽器向跨源服務(wù)器,發(fā)出XMLHttpRequest請求,從而克服了AJAX只能同源使用的限制。
3.跨域請求解決方案
方式一:配置application.yml文件:
spring: cloud: gateway: globalcors: # 全局的跨域配置 add-to-simple-url-handler-mapping: true # 解決options請求被攔截問題 # options請求 就是一種詢問服務(wù)器是否瀏覽器可以跨域的請求 # 如果每次跨域都有詢問服務(wù)器是否瀏覽器可以跨域?qū)π阅芤彩菗p耗 # 可以配置本次跨域檢測的有效期maxAge # 在maxAge設(shè)置的時間范圍內(nèi),不去詢問,統(tǒng)統(tǒng)允許跨域 corsConfigurations: '[/**]': allowedOrigins: # 允許哪些網(wǎng)站的跨域請求 - "http://localhost:8090" allowedMethods: # 允許的跨域ajax的請求方式 - "GET" - "POST" - "DELETE" - "PUT" - "OPTIONS" allowedHeaders: "*" # 允許在請求中攜帶的頭信息 allowCredentials: true # 允許在請求中攜帶cookie maxAge: 360000 # 本次跨域檢測的有效期(單位毫秒) # 有效期內(nèi),跨域請求不會一直發(fā)option請求去增大服務(wù)器壓力
方式二:使用編碼方式定義配置類:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; import org.springframework.http.HttpStatus; import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.http.server.reactive.ServerHttpResponse; import org.springframework.web.cors.reactive.CorsUtils; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebFilter; import org.springframework.web.server.WebFilterChain; import reactor.core.publisher.Mono; @Configuration public class CorsConfig { private static final String MAX_AGE = "18000L"; @Bean public WebFilter corsFilter() { return (ServerWebExchange ctx, WebFilterChain chain) -> { ServerHttpRequest request = ctx.getRequest(); // 使用SpringMvc自帶的跨域檢測工具類判斷當(dāng)前請求是否跨域 if (!CorsUtils.isCorsRequest(request)) { return chain.filter(ctx); } HttpHeaders requestHeaders = request.getHeaders(); // 獲取請求頭 ServerHttpResponse response = ctx.getResponse(); // 獲取響應(yīng)對象 HttpMethod requestMethod = requestHeaders.getAccessControlRequestMethod(); // 獲取請求方式對象 HttpHeaders headers = response.getHeaders(); // 獲取響應(yīng)頭 headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, requestHeaders.getOrigin()); // 把請求頭中的請求源(協(xié)議+ip+端口)添加到響應(yīng)頭中(相當(dāng)于yml中的allowedOrigins) headers.addAll(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, requestHeaders.getAccessControlRequestHeaders()); if (requestMethod != null) { headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, requestMethod.name()); // 允許被響應(yīng)的方法(GET/POST等,相當(dāng)于yml中的allowedMethods) } headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"); // 允許在請求中攜帶cookie(相當(dāng)于yml中的allowCredentials) headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "*"); // 允許在請求中攜帶的頭信息(相當(dāng)于yml中的allowedHeaders) headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, MAX_AGE); // 本次跨域檢測的有效期(單位毫秒,相當(dāng)于yml中的maxAge) if (request.getMethod() == HttpMethod.OPTIONS) { // 直接給option請求反回結(jié)果 response.setStatusCode(HttpStatus.OK); return Mono.empty(); } return chain.filter(ctx); // 不是option請求則放行 }; } }
到此這篇關(guān)于springboot使用Gateway做網(wǎng)關(guān)并且配置全局?jǐn)r截器的文章就介紹到這了,更多相關(guān)springboot Gateway全局?jǐn)r截器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
淺談java Iterator.remove()方法的用法(詳解)
下面小編就為大家?guī)硪黄獪\談java Iterator.remove()方法的用法(詳解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-01-01Java中如何使用Redis GEO測算經(jīng)緯度距離
GEO也是Redis中提供的一種數(shù)據(jù)類型,可以將其理解成ZSet有序集合類型,本文給大家介紹Java-使用Redis GEO測算經(jīng)緯度距離,感興趣的朋友一起看看吧2023-11-11Spring?Boot+Aop記錄用戶操作日志實(shí)戰(zhàn)記錄
在Spring框架中使用AOP配合自定義注解可以方便的實(shí)現(xiàn)用戶操作的監(jiān)控,下面這篇文章主要給大家介紹了關(guān)于Spring?Boot+Aop記錄用戶操作日志實(shí)戰(zhàn)的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-04-04SpringBoot整合Mybatis Plus多數(shù)據(jù)源的實(shí)現(xiàn)示例
本文主要介紹了SpringBoot整合Mybatis Plus多數(shù)據(jù)源的實(shí)現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-11-11springboot3生成本地文件url的實(shí)現(xiàn)示例
本文主要介紹了springboot3生成本地文件url的實(shí)現(xiàn)示例,從而提供一種高效的文件管理方式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-01-01java如何自動補(bǔ)齊數(shù)值至指定位數(shù)
這篇文章主要介紹了java如何自動補(bǔ)齊數(shù)值至指定位數(shù)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-01-01關(guān)于Spring?Validation數(shù)據(jù)校檢的使用流程分析
在實(shí)際項目中,對客戶端傳遞到服務(wù)端的參數(shù)進(jìn)行校驗至關(guān)重要,SpringValidation提供了一種便捷的方式來實(shí)現(xiàn)這一需求,通過在POJO類的屬性上添加檢查注解,本文給大家介紹Spring?Validation數(shù)據(jù)校檢的使用流程,感興趣的朋友一起看看吧2024-11-11