之前http調用都是自己封裝的HttpClients,比較麻煩。最近發現有新的API:RestTemplate可以直接調用接口,非常方便,省得自己封裝請求了。
開始使用:
String url = targetInfoUrl +"?userId={userId}";
Map<String,Object> paramMap = new HashMap(1);
paramMap.put("userId",userId);
Response response = new RestTemplate().getForObject(url, Response.class, paramMap);
被請求接口的返回值是Response類,結構如下:
public class Response<T> {
public String code;
public String msg;
@JsonInclude(value = JsonInclude.Include.NON_NULL)
public T data;
}
其中data具體的值是一個List<MemberInfoAndTargetInfo>。這個MemberInfoAndTargetInfo類的屬性又有一個List<TargetInfoBean>
public class MemberInfoAndTargetInfo {
private String userId;
/**
* 用戶目標信息
*/
private List<TargetInfoBean> targetInfos;
}
我在獲取到Response時,進行強制轉換失敗,編譯不會報錯,運行期報錯
List<MemberInfoAndTargetInfo> data1 = (List<MemberInfoAndTargetInfo>) response.getData();
報錯原因是Map不能被強制轉換爲List。這才發現自己忘記反序列化了,被getForObject方法:
@Override
@Nullable
public <T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables) throws RestClientException {
RequestCallback requestCallback = acceptHeaderRequestCallback(responseType);
HttpMessageConverterExtractor<T> responseExtractor =
new HttpMessageConverterExtractor<>(responseType, getMessageConverters(), logger);
return execute(url, HttpMethod.GET, requestCallback, responseExtractor, uriVariables);
}
的第二個參數迷惑了,自以爲它會幫我反序列化。其實返回的是Response類型的json格式數據,需要我自己再反序列化。查看源碼,這個responseType也僅表示類的名稱等類型信息。於是自己就反序列化一下:
String stringObject = new RestTemplate().getForObject(url, String.class, paramMap);
Object data = JSONObject.parseObject(stringObject).get(ConstantConfig.DATA);
List<MemberInfoAndTargetInfo> targetInfos = JSONArray.parseArray(data.toString(), MemberInfoAndTargetInfo.class);
轉化的過程,又發現MemberInfoAndTargetInfo類的屬性有一個List<TargetInfoBean>無法反序列化,報錯說缺少構造方法。我查看代碼,發現MemberInfoAndTargetInfo類有方法:
public void setTargetInfos(List<TargetInfoBean> targetInfos) {
this.targetInfos = targetInfos;
}
於是查看TargetInfoBean類,發現它少了一個無參的構造方法,補上後,成功。