java如何動(dòng)態(tài)的處理接口的返回?cái)?shù)據(jù)
0、需求說明
業(yè)務(wù)場(chǎng)景:服務(wù)A對(duì)接了服務(wù)B,服務(wù)C等服務(wù)的一些接口,然后由服務(wù)A統(tǒng)一暴露接口給到外部用戶使用。
需求是:
- 服務(wù)A可以動(dòng)態(tài)的接入服務(wù)B/C的接口,對(duì)外暴露并無需重啟(不在本文的討論)
- 對(duì)接的服務(wù)B/C的接口部分字段需要過濾掉,不透出給外部用戶(如數(shù)據(jù)庫(kù)的自增ID等敏感信息)。
1、 思路方案
基本思路:在服務(wù)A里對(duì)各個(gè)服務(wù)接口返回的數(shù)據(jù)進(jìn)行攔截并二次加工后再返回給前端。
攔截:比較簡(jiǎn)單,可以在服務(wù)A對(duì)其他服務(wù)接口請(qǐng)求的返回之后進(jìn)行業(yè)務(wù)操作,也可以統(tǒng)一放到切面里用 @After 注解進(jìn)行操作。從 demo 的快速演示考慮,這里選擇直接在請(qǐng)求的返回體直接進(jìn)行業(yè)務(wù)操作。
二次加工:服務(wù)A對(duì)返回body的部分字段過濾掉,不返回給前端。二次加工的方法有很多種,比如:
a. 用一個(gè) map 去接收 body,然后對(duì)這個(gè) body map 進(jìn)行遍歷,和服務(wù)A里的 map 進(jìn)行比較, 將服務(wù)A map 里需要的 key-value,從 body map 里遍歷取出,put 到一個(gè)新的 map,最后返回這個(gè)新的 map 給前端。
b. 用 string 去接收 body,接收到的body是一個(gè) json 字符串,然后將 json 字符串轉(zhuǎn)成特定的對(duì)象(這個(gè)對(duì)象是返回給前端的),這樣對(duì)象里沒有定義的字段在 json 字符串轉(zhuǎn)對(duì)象的過程中就會(huì)被舍棄。
方案a有幾個(gè)缺陷:
- 首先,要求其他服務(wù)接口的返回必須是一個(gè) json 類型(可用 map 接收),如果是一個(gè) json數(shù)組([{},{}])的話, 就無法用map接收,這樣會(huì)導(dǎo)致對(duì)接入服務(wù)的接口數(shù)據(jù)結(jié)構(gòu)有限制,不ok;
- 其次,map 數(shù)據(jù)類型可能會(huì)很復(fù)雜,由于不確定 map 里的 value的數(shù)據(jù)結(jié)構(gòu)是 string,list 還是 map 等,就需要用 instanceof 對(duì)所有的數(shù)據(jù)結(jié)構(gòu)進(jìn)行遍歷判斷再比較賦值,很復(fù)雜,計(jì)算效率也不高。
- 沒有可利用的輪子,類似將對(duì)象A賦值給對(duì)象B的屬性拷貝(BeanUtils.copyProperties()),可以將mapA的 key-value 賦值給mapB
# mapA { "a": "a", "b": "b", "c": "c" } # mapB { "a": null, "b": null, }
相反,方案b有一個(gè)很大的優(yōu)勢(shì):可以利用現(xiàn)成的序列化和反序列化工具(如Gson)來實(shí)現(xiàn)我們的需求。先放一個(gè)反序列化的工具,后面會(huì)用到:
/** * Json字符串轉(zhuǎn)為指定的對(duì)象 * @param ret json字符串 * @param clazz 指定對(duì)象的類 * @return T 指定的對(duì)象 */ public class JsonUtil { public static <T> T jsonStr2Obj(String ret, Class<T> clazz) { Gson gson = new Gson(); return gson.fromJson(ret, (Type) clazz); } }
但是說到這里,解決的只是對(duì)接口返回body的修改,沒有體現(xiàn)出標(biāo)題的“動(dòng)態(tài)”二字。那么如何可以動(dòng)態(tài)的對(duì)返回的body數(shù)據(jù)進(jìn)行過濾處理呢?用 groovy 動(dòng)態(tài)加載類。
2 、 具體實(shí)施
- 獲取接口的返回(以string類型):
ResponseEntity<String> exchange = restTemplate.getForEntity($url, String.class); String body = exchange.getBody();
- 通過groovy獲取動(dòng)態(tài)編譯類
String clazzInString = getFromRedis($key) // 從redis獲取字符串類型的java class Object obj = DynamicClassCompilerUtil.run(clazzInString)
public class DynamicClassCompilerUtil { public static Object run(String cls) { Class<?> clazz = new GroovyClassLoader().parseClass(cls); try { return clazz.newInstance(); } catch (Exception e) { log.error("parse groovy class failed: {}", e); return null; } } }
- 將 body 反序列化
Object ret = JsonUtil.jsonStr2Obj(body, o.getClass())
該 ret 對(duì)象即為過濾后的對(duì)象,可以加工后返回給前端。
至此,“對(duì)接的服務(wù)B/C的接口部分字段需要過濾掉,不透出給外部用戶(如數(shù)據(jù)庫(kù)的自增ID等敏感信息)” 需求實(shí)現(xiàn)了。
至于 “服務(wù)A可以動(dòng)態(tài)的接入服務(wù)B/C的接口,對(duì)外暴露并無需重啟” 需求,有時(shí)間的話,將會(huì)另起一篇來講。
到此這篇關(guān)于java如何動(dòng)態(tài)的處理接口的返回?cái)?shù)據(jù)的文章就介紹到這了,更多相關(guān)java 動(dòng)態(tài)處理接口的返回?cái)?shù)據(jù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 如何使用java制作假數(shù)據(jù)接口
- Java?如何通過注解實(shí)現(xiàn)接口輸出時(shí)數(shù)據(jù)脫敏
- Java實(shí)現(xiàn)調(diào)用對(duì)方http接口得到返回?cái)?shù)據(jù)
- Java 利用DeferredResult實(shí)現(xiàn)http輪詢實(shí)時(shí)返回?cái)?shù)據(jù)接口
- java讀取其他服務(wù)接口返回的json數(shù)據(jù)示例代碼
- Java編程通過list接口實(shí)現(xiàn)數(shù)據(jù)的增刪改查代碼示例
- Linux實(shí)時(shí)查看Java接口數(shù)據(jù)的案例方法
相關(guān)文章
多個(gè)springboot項(xiàng)目如何使用一個(gè)外部共同的application.yml
這篇文章主要介紹了多個(gè)springboot項(xiàng)目如何使用一個(gè)外部共同的application.yml問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-05-05Java通過CMD方式讀取注冊(cè)表任意鍵值對(duì)代碼實(shí)踐
這篇文章主要介紹了Java通過CMD方式讀取注冊(cè)表任意鍵值對(duì)代碼實(shí)踐,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,,需要的朋友可以參考下2019-06-06mybatis createcriteria和or的區(qū)別說明
這篇文章主要介紹了mybatis createcriteria和or的區(qū)別說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-07-07Jlabel實(shí)現(xiàn)內(nèi)容自動(dòng)換行簡(jiǎn)單實(shí)例
這篇文章主要介紹了Jlabel實(shí)現(xiàn)內(nèi)容自動(dòng)換行簡(jiǎn)單實(shí)例,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-01-01java WSDL接口webService實(shí)現(xiàn)方式
這篇文章主要為大家詳細(xì)介紹了java WSDL接口webService實(shí)現(xiàn)方式的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04解析Java中所有錯(cuò)誤和異常的父類java.lang.Throwable
這篇文章主要介紹了Java中所有錯(cuò)誤和異常的父類java.lang.Throwable,文章中簡(jiǎn)單地分析了其源碼,說明在代碼注釋中,需要的朋友可以參考下2016-03-03淺談HttpClient、okhttp和RestTemplate的區(qū)別
這篇文章主要介紹了HttpClient、okhttp和RestTemplate的區(qū)別,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06