Spring Gateway自定義請(qǐng)求參數(shù)封裝的實(shí)現(xiàn)示例
一、需求
在使用spring gateway作為網(wǎng)關(guān)時(shí),我們需要在經(jīng)過(guò)網(wǎng)關(guān)的請(qǐng)求中添加一些需要傳遞給后續(xù)服務(wù)的公共參數(shù),這個(gè)時(shí)候就可以用到spring gateway提供的自定義請(qǐng)求參數(shù)功能了。
二、尋找解決途徑
1、參考官方文檔
我們可以猜測(cè),spring gateway作為網(wǎng)關(guān)功能,肯定會(huì)提供很多處理請(qǐng)求參數(shù)的功能,于是我們查詢文檔得到如下內(nèi)容:
2、探索GatewayFilterFactory實(shí)現(xiàn)規(guī)律
- 通過(guò)查詢spring官方文檔可以看到,spring gateway為我們提供了很多
xxxGatewayFilterFactory
,而這些factory
都有相同點(diǎn),都是以GatewayFilterFactory
結(jié)尾的。 - 在類名中,我們可以根據(jù)類名進(jìn)行大膽的猜測(cè),前面的幾個(gè)單詞是描述他的功能的。
- 右側(cè)的
yml
配置文件可以看到,filter的配置也是呈現(xiàn)出一定的規(guī)律的。
3、從源碼獲取實(shí)現(xiàn)原理
既然我們是要解決自定義請(qǐng)求參數(shù)封裝問(wèn)題,那么我們通過(guò)上面描述規(guī)律,可以很大膽的猜測(cè)AddRequestParameteGatewayFilterFactory
就是我們要找的目標(biāo)。那么我們查看一下他的源碼,看看他是如何實(shí)現(xiàn)的。
首先看看AddRequestParameteGatewayFilterFactory
的繼承關(guān)系,大概了解一下他的組成
從繼承關(guān)系來(lái)看,還是比較復(fù)雜,有點(diǎn)懵逼,那直接進(jìn)入代碼看看他的實(shí)現(xiàn)。
我們只粘貼比較核心的代碼進(jìn)行分析,其他代碼暫時(shí)不用關(guān)心。
@Override public GatewayFilter apply(NameValueConfig config) { return new GatewayFilter() { @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { URI uri = exchange.getRequest().getURI(); StringBuilder query = new StringBuilder(); //獲取請(qǐng)求uri的請(qǐng)求參數(shù)(GET請(qǐng)求參數(shù)通過(guò)拼接key=value形式進(jìn)行傳參) String originalQuery = uri.getRawQuery(); //判斷最后一個(gè)字符是否是&,如果不是則拼接一個(gè)&,以備后續(xù)的參數(shù)進(jìn)行連接 if (StringUtils.hasText(originalQuery)) { query.append(originalQuery); if (originalQuery.charAt(originalQuery.length() - 1) != '&') { query.append('&'); } } //獲取config中的key、value,然后拼接到uri請(qǐng)求參數(shù)后面 String value = ServerWebExchangeUtils.expand(exchange, config.getValue()); // TODO urlencode? query.append(config.getName()); query.append('='); query.append(value); //把請(qǐng)求參數(shù)重新拼接回去,并放入request中傳遞到過(guò)濾鏈的下一個(gè)請(qǐng)求中去 try { URI newUri = UriComponentsBuilder.fromUri(uri) .replaceQuery(query.toString()).build(true).toUri(); ServerHttpRequest request = exchange.getRequest().mutate().uri(newUri) .build(); return chain.filter(exchange.mutate().request(request).build()); } catch (RuntimeException ex) { throw new IllegalStateException( "Invalid URI query: \"" + query.toString() + "\""); } }
此方法是用于封裝請(qǐng)求參數(shù)的具體實(shí)現(xiàn),代碼的具體實(shí)現(xiàn)步驟已經(jīng)通過(guò)注釋進(jìn)行說(shuō)明。
那config
中的key:value又是如何傳遞進(jìn)來(lái)的呢?
4、filter的配置和參數(shù)傳遞
代碼實(shí)現(xiàn)中出現(xiàn)了config
參數(shù)的封裝,那這個(gè)參數(shù)是如何獲得的呢?這時(shí)候我們就要去查看這個(gè)filter是如何使用的了。
- 從圖中可以看到,我們的filter就是在這個(gè)配置文件中配置使用的。那為什么配置文件中只有
AddRequestParameter
配置,而不是AddRequestParameterGatewayFilterFactory
呢??? - 其實(shí)這是spring的一種約定,實(shí)現(xiàn)了
GatewayFilterFactory
接口的類在配置使用的時(shí)候,需要省略掉后面的GatewayFilterFactory
,僅配置前綴即可。 - 同時(shí),配置文件中的red,blue又是做什么的???
- 這就是我們需要傳遞的請(qǐng)求參數(shù)了,他以key=red,value=blue的方式進(jìn)行配置。
- 然后spring會(huì)幫我們把這個(gè)鍵值傳入到上面的apply方法的config中。我們通過(guò)config的源碼就能看到究竟:
可以看到,config類的實(shí)現(xiàn)就是一個(gè)name
和value
,分別對(duì)應(yīng)了配置文件中的兩個(gè)參數(shù)。
三、基于官方實(shí)現(xiàn)進(jìn)行自定義拓展
我們看到,spring利用同種方式,實(shí)現(xiàn)了各種filter。但如果這些都不能滿足我們的要求,那該怎么辦???
1、自定義參數(shù)慘景預(yù)設(shè)
我們現(xiàn)在看到的參數(shù)信息都是寫死在配置文件中的,無(wú)法進(jìn)行動(dòng)態(tài)參數(shù)的傳遞。我們可以設(shè)想一個(gè)很普通的場(chǎng)景: 我們需要把用戶的登錄信息封裝到請(qǐng)求參數(shù)中,供其他服務(wù)使用。那這又該如何實(shí)現(xiàn)呢???
2、參考官方實(shí)現(xiàn)進(jìn)行自定義
其實(shí)如果我們只要模仿官方實(shí)現(xiàn),在uri上拼接我們要傳遞的動(dòng)態(tài)參數(shù)就可以了。具體實(shí)現(xiàn)如下:
@Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { URI uri = exchange.getRequest().getURI(); StringBuilder query = new StringBuilder(); String originalQuery = uri.getRawQuery(); if (StringUtils.hasText(originalQuery)) { query.append(originalQuery); if (originalQuery.charAt(originalQuery.length() - 1) != '&') { query.append('&'); } } String value = ServerWebExchangeUtils.expand(exchange, config.getValue()); // TODO urlencode? query.append(config.getName()); query.append('='); query.append(value); //獲取redis中用戶的緩存信息,拼接到請(qǐng)求參數(shù)后面 String token = exchange.getRequest().getHeaders().getFirst("token"); if (StringUtils.hasText(token)) { AccountEntity accountEntity = accountAdminApiService.loginAccountAdmin(token); //通過(guò)發(fā)射拿到bean的屬性和值,以備后面進(jìn)行傳遞參數(shù)拼接 Map<String, Object> beanMap = beanValue(accountEntity); if (!CollectionUtils.isEmpty(beanMap)) { for (String key : beanMap.keySet()) { query.append('&').append(key).append('=').append(beanMap.get(key)); } } } //以下與官方代碼一樣,省略... }
在固定傳參參數(shù)拼接后面,直接通過(guò)token去獲取緩存中的用戶登陸信息,然后依次拼接對(duì)應(yīng)的屬性和值即可。
四、自定義filter的應(yīng)用。
網(wǎng)上看了很多人寫的自定義,其實(shí)和本文差不多。但是有點(diǎn)沒(méi)有提到,定義好了怎么用?。???
通過(guò)使用注解@bean
的方式進(jìn)行配置,具體可以自己百度。
這里用一個(gè)簡(jiǎn)易的配置,套用yml
配置的規(guī)律,直接在配置文件中配置。
default-filters: - AccountRequestParameter=k, v
因?yàn)槲沂侨质褂玫?,所以使用的?code>default-filters進(jìn)行配置
此外還應(yīng)該注意,此時(shí)自定的filter并不會(huì)被spring boot加載,所以在啟動(dòng)的時(shí)候會(huì)報(bào)錯(cuò)。
解決辦法:此時(shí)還要在對(duì)應(yīng)的類上加上注解@Component
,把bean交給spring管理。
至此,我們自定義請(qǐng)求參數(shù)封裝完成?。?!
到此這篇關(guān)于Spring Gateway自定義請(qǐng)求參數(shù)封裝的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)Spring Gateway自定義請(qǐng)求參數(shù)封裝內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解Spring Cloud Zuul 服務(wù)網(wǎng)關(guān)
本篇文章主要介紹了詳解Spring Cloud Zuul 服務(wù)網(wǎng)關(guān),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-12-12Java實(shí)現(xiàn)將類數(shù)據(jù)逐行寫入CSV文件的方法詳解
這篇文章主要為大家詳細(xì)介紹了Java如何實(shí)現(xiàn)將類數(shù)據(jù)逐行寫入CSV文件,文中的示例代碼講解詳細(xì),具有一定的參考價(jià)值,需要的可以借鑒一下2022-11-11Java IO流之節(jié)點(diǎn)流與字符流的相關(guān)知識(shí)總結(jié)
今天給大家?guī)?lái)的是關(guān)于Java的相關(guān)知識(shí),文章圍繞著Java節(jié)點(diǎn)流與字符流展開(kāi),文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-06-06java實(shí)現(xiàn)IP地址轉(zhuǎn)換
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)IP地址轉(zhuǎn)換,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11解決elastic-job-ui在使用druid作為數(shù)據(jù)庫(kù)連接池時(shí)作業(yè)維度報(bào)錯(cuò)問(wèn)題
這篇文章主要介紹了解決elastic-job-ui在使用druid作為數(shù)據(jù)庫(kù)連接池時(shí)作業(yè)維度報(bào)錯(cuò)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-04-04java實(shí)現(xiàn)動(dòng)態(tài)編譯并動(dòng)態(tài)加載
這篇文章主要介紹了java實(shí)現(xiàn)動(dòng)態(tài)編譯并動(dòng)態(tài)加載,需要的朋友可以參考下2021-04-04解決Spring boot 嵌入的tomcat不啟動(dòng)問(wèn)題
這篇文章主要介紹了解決Spring boot 嵌入的tomcat不啟動(dòng)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-10-10Java通過(guò)正則表達(dá)式獲取字符串中數(shù)字的方法示例
最近工作中遇到了一個(gè)需求,需要利用java獲取字符串中的數(shù)字,嘗試幾種方法后發(fā)現(xiàn)利用正則表達(dá)式實(shí)現(xiàn)最為方法,下面這篇文章就主要介紹了Java通過(guò)正則表達(dá)式獲取字符串中數(shù)字的方法,文中給出了詳細(xì)的示例代碼,需要的朋友可以參考下。2017-03-03Spring Eureka 未授權(quán)訪問(wèn)漏洞修復(fù)問(wèn)題小結(jié)
項(xiàng)目組使用的 Spring Boot 比較老,是 1.5.4.RELEASE ,最近被檢測(cè)出 Spring Eureka 未授權(quán)訪問(wèn)漏洞,這篇文章主要介紹了Spring Eureka 未授權(quán)訪問(wèn)漏洞修復(fù)問(wèn)題小結(jié),需要的朋友可以參考下2024-04-04