RestTemplate將響應數據轉換為具有泛型的類對象


前言:

重要,RestTemplate在SpringBoot項目里即便通過HttpMessageConverters添加了Fastjson且優先級比jackson要高也不會在RestTemplate里生效

,換句話說RestTemplate如果要使用Fastjson還是要對RestTemplate進行額外配置,而不是在SpringBoot項目里配置了類型是HttpMessageConverters的Bean就可以了;

方式可以參考:https://www.jianshu.com/p/c9644755dd5e

一:沒有泛型的情況(這里以POST舉例,但是對於GET也是一樣的)

CommonResponse response = restTemplate.postForObject(remoteUrl, tokenRequest, CommonResponse.class);

這里tokenRequest是請求體對象,將會由Fastjson序列化為JSON字符串,它所屬的類無所謂是不是有泛型,因為可以通過member.getClass()獲得(即tokenRequest中所有的成員的類型是確立的且可獲取的);

使用的時候最好用restTemplate.postForEntity()的而不要用restTemplate.postForObject(),后者不能設置Header,而且似乎也不能執行Multipart請求;

二:有泛型的情況

CommonResponse<TokenDataModel> response = restTemplate.postForObject(remoteUrl, tokenRequest, CommonResponse.class);

這個時候就有問題了,因為CommonResponse在字節碼里是泛型擦除的,它所有的泛型成員本質上就是一個Object類型的子類但是.class里沒有記錄到底是什么具體類,因此當獲取的response的JSON字符串中:

{
    "code": 8209,
    "code_description": "APPLICANT_SUCCESS",
    "data": {
        "cell_phone_number": "1111111111",
        "collect_website": "中國聯通","token": "77785fb276ed47cb9a01ec52f9a133c8"
    },
    "message": "成功"
}

將data部分轉換為泛型成員時RestTemplate將不知道該怎么轉換,如果將T類型認為是Object,那么顯然Object是沒有cellPhoneNumber之類的屬性的,所以RestTemplate的做法是將data部分的JSON字符串轉換為了LinkedHashMap對象(key-value對);

三:解決方式

通過RestTemplate的exchange方法來解決:

ParameterizedTypeReference<CommonResponse<TokenDataModel>> typeRef = new ParameterizedTypeReference<CommonResponse<TokenDataModel>>() {};
// exchange並不對應於任何一種method,如GET、POST、PUT、DELETE,因此需要手動指定 CommonResponse
<TokenDataModel> response = restTemplate.exchange(remoteUrl, HttpMethod.POST, new HttpEntity<>(tokenRequest), typeRef).getBody();

四:單純用Fastjson轉換有泛型的類的方式

CommonResponse<TokenDataModel> response = JSON.parseObject("{json string}", new com.alibaba.fastjson.TypeReference<CommonResponse<TokenDataModel>>(){});

五:原理

在java里,泛型類編譯成.class后確實是泛型擦除,但是泛型類對象里是會(間接)存儲泛型的實際類型的,因此需要new TypeReference<Test<RealType>>(){}產生一個對象;

它內部是:

// 獲取匿名類對象的Generic父類,即Test<RealType>類型
// 注意superClass並不是Class類對象,它應該理解為:
// 為泛型類的子匿名類對象產生的一個與之一一對應的Type類對象(這個倒像真泛型)
// 這個Type類對象里存儲了此匿名類對象的所有泛型信息
Type superClass = getClass().getGenericSuperclass();


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM