利用feign調(diào)用返回object類型轉(zhuǎn)換成實體
feign調(diào)用返回object轉(zhuǎn)成實體
<dependency> ? ? <groupId>com.fasterxml.jackson.core</groupId> ? ? <artifactId>jackson-databind</artifactId> ? ? <version>2.9.8</version> </dependency>
ObjectMapper mapper=new ObjectMapper(); CourseMaster courseMaster = mapper.convertValue(bean,CourseMaster.class); List<CourseMaster> list=(List<CourseMaster>)courseMasterList;//返回為Object類型 for(Object cs:list){ ? ? CourseMaster courseMaster = mapper.convertValue(cs,CourseMaster.class); }
feign調(diào)用報類型轉(zhuǎn)換錯誤
問題現(xiàn)象
springcloud feign服務(wù)間調(diào)用,運行至下圖1代碼A處報錯:
java.util.LinkedHashMap cannot be cast to(報錯如下圖2所示)
排查過程
step1:大多數(shù)情況下,第一反應(yīng)是仔細(xì)檢查語法是否有問題,確認(rèn)lambda表達(dá)式本身沒有問題;
step2:在確認(rèn)寫的沒有問題的情況下,將代碼片段拎出來寫一個main方法運行(如圖1代碼片段B),發(fā)現(xiàn)單獨拿出來在main方法中運行時正常!
step3:此時陷入困惑,于是重新仔細(xì)閱讀報錯信息:LinkedHashMap cannot be cast to xxx.BaseComapny,可以很清楚的確定是類型轉(zhuǎn)換錯誤。
再一行一行看代碼(圖1中代碼片段A),發(fā)現(xiàn)只有在代碼片段A上方的:List list = xxxxx這一段中有可能的類型轉(zhuǎn)換,所以暫時定位至此行代碼。
step4:step3中的推測不確定的原因在于:此行代碼中responseObject是直接通過服務(wù)調(diào)用獲取到的,請求響應(yīng)參數(shù)中已指定了對象類型,所以我認(rèn)為這里不存在強制類型轉(zhuǎn)換,也不存在LinkedHashMap。
繼續(xù)沿著上面的推測,如果確實存在問題,那只可能是通過服務(wù)調(diào)用獲取到的返回參數(shù)與預(yù)期不一致,step5:于是分別對上面圖1中代碼A和代碼B(也就是main方法)做debug,結(jié)果如下圖所示,發(fā)現(xiàn)確實服務(wù)調(diào)用后獲取的響應(yīng)參數(shù)與main方法中的不一致??梢钥吹狡蜛服務(wù)調(diào)用得到的響應(yīng)參數(shù)list中確實是LinkedHashMap!至此發(fā)現(xiàn)問題!
step6:由于確定自己沒有對服務(wù)調(diào)用前后特殊處理過響應(yīng)參數(shù),所以考慮這是框架行為,至此問題基本找到原因。
問題原因
找出原因后再針對性的百度答案就比較容易得到,簡單來說就是使用feign進(jìn)行遠(yuǎn)程服務(wù)調(diào)用的時候,返回參數(shù)(在我的代碼中,Response中的list部分)會變成LinkedHashMap。
以下是網(wǎng)上能找到的流傳最多的解釋(因為復(fù)制這段話的文章和博客太多了,無法確認(rèn)誰復(fù)制了誰,也無法確認(rèn)第一個寫的作者是誰,所以無法標(biāo)注出原作者):
這是因為RPC遠(yuǎn)程調(diào)用在底層使用的HTTPClient,所以在傳遞參數(shù)的時候,必定要有個順序,當(dāng)你傳遞Map的時候Map里面的值也要有順序,不然服務(wù)層在接的時候就出問題了,所以它才會從Map轉(zhuǎn)為LinkedHashMap!Spring 有一個類叫ModelMap,繼承了LinkedHashMap ,所以一個接口返回的結(jié)果就可以直接用ModelMap來接,注意ModelMap是沒有泛型的,不管你返回的結(jié)果是什么類型的Map,泛型是多復(fù)雜的Map,都可以直接new一個ModelMap,用它來接返回的結(jié)果。
解決辦法
1、最簡單的解決辦法就是在接收響應(yīng)參數(shù)的地方直接用LinkedHashMap接收,通過kv形式獲取到參數(shù);
2、通過json,objectmapper等方式將LinkedHashMap轉(zhuǎn)換成自己想要的對象;
3、對feign調(diào)用得到的響應(yīng)參數(shù)做自定義處理(也許可以?);
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java虛擬機JVM性能優(yōu)化(一):JVM知識總結(jié)
這篇文章主要介紹了Java虛擬機JVM性能優(yōu)化(一):JVM知識總結(jié),本文是系列文章的第一篇,后續(xù)篇章請繼續(xù)關(guān)注腳本之家,需要的朋友可以參考下2014-09-09Mybatis傳遞多個參數(shù)進(jìn)行SQL查詢的用法
本文給大家介紹Mybatis傳遞多個參數(shù)進(jìn)行SQL查詢的用法的相關(guān)知識,本文還給大家介紹了mybatis通過Map傳遞多個參數(shù)和JavaBean傳遞多個參數(shù),本文介紹的非常詳細(xì),具有參考借鑒價值,感興趣的朋友一起學(xué)習(xí)吧2016-06-06Java中的WeakHashMap、LinkedHashMap、TreeMap與Set詳解
這篇文章主要介紹了Java中的WeakHashMap、LinkedHashMap、TreeMap與Set詳解,在JVM中,一個對象如果不再被使用就會被當(dāng)做垃圾給回收掉,判斷一個對象是否是垃圾,我們的WeakHashMap就是基于弱引用,需要的朋友可以參考下2023-09-09springboot+mybatis+redis 二級緩存問題實例詳解
Mybatis默認(rèn)沒有開啟二級緩存,需要在全局配置(mybatis-config.xml)中開啟二級緩存。本文講述的是使用Redis作為緩存,與springboot、mybatis進(jìn)行集成的方法。需要的朋友參考下吧2017-12-12JAVA基于SnakeYAML實現(xiàn)解析與序列化YAML
這篇文章主要介紹了JAVA基于SnakeYAML實現(xiàn)解析與序列化YAML,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-12-12