Spring Gateway自定義請求參數(shù)封裝的實現(xiàn)示例
一、需求
在使用spring gateway作為網(wǎng)關時,我們需要在經(jīng)過網(wǎng)關的請求中添加一些需要傳遞給后續(xù)服務的公共參數(shù),這個時候就可以用到spring gateway提供的自定義請求參數(shù)功能了。
二、尋找解決途徑
1、參考官方文檔
我們可以猜測,spring gateway作為網(wǎng)關功能,肯定會提供很多處理請求參數(shù)的功能,于是我們查詢文檔得到如下內容:
2、探索GatewayFilterFactory實現(xiàn)規(guī)律
通過查詢spring官方文檔可以看到,spring gateway為我們提供了很多xxxGatewayFilterFactory,而這些factory都有相同點,都是以GatewayFilterFactory結尾的。 在類名中,我們可以根據(jù)類名進行大膽的猜測,前面的幾個單詞是描述他的功能的。 右側的yml配置文件可以看到,filter的配置也是呈現(xiàn)出一定的規(guī)律的。3、從源碼獲取實現(xiàn)原理
既然我們是要解決自定義請求參數(shù)封裝問題,那么我們通過上面描述規(guī)律,可以很大膽的猜測AddRequestParameteGatewayFilterFactory就是我們要找的目標。那么我們查看一下他的源碼,看看他是如何實現(xiàn)的。
首先看看AddRequestParameteGatewayFilterFactory的繼承關系,大概了解一下他的組成
從繼承關系來看,還是比較復雜,有點懵逼,那直接進入代碼看看他的實現(xiàn)。
我們只粘貼比較核心的代碼進行分析,其他代碼暫時不用關心。
@Overridepublic GatewayFilter apply(NameValueConfig config) {return new GatewayFilter() {@Overridepublic Mono<Void> filter(ServerWebExchange exchange,GatewayFilterChain chain) {URI uri = exchange.getRequest().getURI();StringBuilder query = new StringBuilder();//獲取請求uri的請求參數(shù)(GET請求參數(shù)通過拼接key=value形式進行傳參) String originalQuery = uri.getRawQuery(); //判斷最后一個字符是否是&,如果不是則拼接一個&,以備后續(xù)的參數(shù)進行連接if (StringUtils.hasText(originalQuery)) {query.append(originalQuery);if (originalQuery.charAt(originalQuery.length() - 1) != ’&’) {query.append(’&’);}}//獲取config中的key、value,然后拼接到uri請求參數(shù)后面String value = ServerWebExchangeUtils.expand(exchange, config.getValue());// TODO urlencode?query.append(config.getName());query.append(’=’);query.append(value);//把請求參數(shù)重新拼接回去,并放入request中傳遞到過濾鏈的下一個請求中去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() + ''');}}
此方法是用于封裝請求參數(shù)的具體實現(xiàn),代碼的具體實現(xiàn)步驟已經(jīng)通過注釋進行說明。
那config中的key:value又是如何傳遞進來的呢?
4、filter的配置和參數(shù)傳遞
代碼實現(xiàn)中出現(xiàn)了config參數(shù)的封裝,那這個參數(shù)是如何獲得的呢?這時候我們就要去查看這個filter是如何使用的了。
可以看到,config類的實現(xiàn)就是一個name 和value,分別對應了配置文件中的兩個參數(shù)。
三、基于官方實現(xiàn)進行自定義拓展
我們看到,spring利用同種方式,實現(xiàn)了各種filter。但如果這些都不能滿足我們的要求,那該怎么辦???
1、自定義參數(shù)慘景預設
我們現(xiàn)在看到的參數(shù)信息都是寫死在配置文件中的,無法進行動態(tài)參數(shù)的傳遞。我們可以設想一個很普通的場景: 我們需要把用戶的登錄信息封裝到請求參數(shù)中,供其他服務使用。那這又該如何實現(xiàn)呢???
2、參考官方實現(xiàn)進行自定義
其實如果我們只要模仿官方實現(xiàn),在uri上拼接我們要傳遞的動態(tài)參數(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中用戶的緩存信息,拼接到請求參數(shù)后面 String token = exchange.getRequest().getHeaders().getFirst('token'); if (StringUtils.hasText(token)) { AccountEntity accountEntity = accountAdminApiService.loginAccountAdmin(token); //通過發(fā)射拿到bean的屬性和值,以備后面進行傳遞參數(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ù)拼接后面,直接通過token去獲取緩存中的用戶登陸信息,然后依次拼接對應的屬性和值即可。
四、自定義filter的應用。
網(wǎng)上看了很多人寫的自定義,其實和本文差不多。但是有點沒有提到,定義好了怎么用啊???
通過使用注解@bean的方式進行配置,具體可以自己百度。
這里用一個簡易的配置,套用yml配置的規(guī)律,直接在配置文件中配置。
default-filters: - AccountRequestParameter=k, v
因為我是全局使用的,所以使用的是default-filters進行配置
此外還應該注意,此時自定的filter并不會被spring boot加載,所以在啟動的時候會報錯。
解決辦法:此時還要在對應的類上加上注解@Component,把bean交給spring管理。
至此,我們自定義請求參數(shù)封裝完成!!!
到此這篇關于Spring Gateway自定義請求參數(shù)封裝的實現(xiàn)示例的文章就介紹到這了,更多相關Spring Gateway自定義請求參數(shù)封裝內容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持好吧啦網(wǎng)!
相關文章:
