在feign介面中返回泛型類(Generic response support for feign client)
在feign介面中返回泛型類時,由於java的泛型機制,在例項化之前無法得到具體的型別 ,因此,雖然服務提供方返回的是具體例項的資料,但是在客戶端decode時,無法轉化為具體的類。
例如
@RequestMapping("getGoodByCode")
<T extends BaseEntity> ObjectResponse<T> geByCode(@RequestParam("code") String code,@RequestParam("type") String type);
此介面 通過商品code和型別獲取商品類,此時我們只能接收到只能是ObjectResponse<BaseEntity>
即使服務方返回的是 ObjectResponse<Goods>
。
解決辦法
呼叫在http header中加入泛型類的ClassType—> 重寫Decoder介面–>獲取header中的泛型類的ClassType---->反序列化
實現步驟:
- 服務提供方返回泛型型別的全限定名 如
com.csdn.product.Goods
可放在header中 - 客戶端繼承Decoder 介面,重寫decode方法。
- 得到類名後和response資料.
- 通過反射例項化Goods,得到Goods 的Class類
- 通過反序列化,得到Goods 類例項,
- 然後set
Response.setModel(goods )
Decoder
public class CustomDecoder implements Decoder {
//泛型的classType ,,decode 方法進行手動解析.
public final static String genericsHeader = "generics-header";
private Decoder decoder;
public CustomDecoder(Decoder decoder) {
this.decoder = decoder;
}
@Override
public Object decode(Response response, Type type) throws IOException, DecodeException, FeignException {
Object returnObject = null;
if (isParameterizeHttpEntity(type)) {
type = ((ParameterizedType) type).getActualTypeArguments()[0];
Object decodedObject = decoder.decode(response,type);
returnObject = createResponse(decodedObject, response);
}
else if (isHttpEntity(type)) {
returnObject = createResponse(null, response);
}
else {
returnObject = decoder.decode(response, type);
}
//以上是原預設實現,複製過來,為了拿到returnObject
if(returnObject !=null) {
Map<String, Collection<String>> map = response.headers();
if (returnObject instanceof ObjectResponse) {
Collection<String> list = map.get(genericsHeader);
if(list!=null){
Object object = ReflectUtil.newInstance(((LinkedList)list).get(0).toString());
String body = IoUtil.read(response.body().asInputStream(),"UTF-8");
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
JsonNode jsonNode = objectMapper.readTree(body);
if(!jsonNode.get("success").booleanValue()){
return returnObject;
}
//拿出result ,例項化物件(genericsHeader 指定的型別),然後重新set
String result = jsonNode.get("model").toString();
((ObjectResponse) returnObject).setModel(objectMapper.readValue(result,object.getClass()));
}
}
}
// log.info("計算耗時:{}",System.currentTimeMillis()-start);
return returnObject;
}
private boolean isParameterizeHttpEntity(Type type) {
if (type instanceof ParameterizedType) {
return isHttpEntity(((ParameterizedType) type).getRawType());
}
return false;
}
private boolean isHttpEntity(Type type) {
if (type instanceof Class) {
Class c = (Class) type;
return HttpEntity.class.isAssignableFrom(c);
}
return false;
}
@SuppressWarnings("unchecked")
private <T> ResponseEntity<T> createResponse(Object instance, Response response) {
MultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
for (String key : response.headers().keySet()) {
headers.put(key, new LinkedList<>(response.headers().get(key)));
}
return new ResponseEntity<>((T) instance, headers, HttpStatus.valueOf(response
.status()));
}
}
ObjectResponse
public class ObjectResponse<T> {
private boolean success;
private String msg;
private T model;
public boolean isSuccess() {
return success;
}
public ObjectResponse<T> setSuccess(boolean success) {
this.success = success;
return this;
}
public String getMsg() {
return msg;
}
public ObjectResponse<T> setMsg(String msg) {
this.msg = msg;
return this;
}
public T getModel() {
return model;
}
public ObjectResponse<T> setModel(T model) {
this.model = model;
return this;
}
}
相關文章
- 泛型(Generic)泛型
- 01.泛型Generic泛型
- TypeScript 泛型介面和泛型類TypeScript泛型
- 【譯】在非泛型類中建立泛型方法泛型
- feign
- SpringCloud-使用Feign呼叫服務介面SpringGCCloud
- 微服務實戰SpringCloud之Spring Cloud Feign替代HTTP Client微服務SpringGCCloudHTTPclient
- Feign系列
- TS系列之介面/類/泛型泛型
- (22)SpringCloud-使用Feign呼叫服務介面SpringGCCloud
- TS類,介面,泛型的簡介泛型
- Springcloud(二) feignSpringGCCloud
- SpringCloud-FeignSpringGCCloud
- Feign的使用
- Feign簡介
- .NET進階篇01-Generic泛型深入泛型
- Spring Feign教程大全Spring
- feign攜帶token
- Feign的工作原理
- SpringCloud Feign的分析SpringGCCloud
- Feign - 原始碼分析原始碼
- Feign快速入門
- Bug集錦-Spring Cloud Feign呼叫其它介面報錯SpringCloud
- 泛型類和泛型方法泛型
- 泛型類、泛型方法及泛型應用泛型
- Feign整合Sentinel 開啟 feign.sentinel.enabled=true 啟動報錯
- 介面即泛型泛型
- springcloud中feign檔案上傳、下載SpringGCCloud
- 微服務呼叫元件 Feign微服務元件
- SpringCloud 2020.0.4 系列之 FeignSpringGCCloud
- Spring Cloud 之 Feign.SpringCloud
- Spring Cloud Feign 應用SpringCloud
- 微服務互相呼叫-Feign微服務
- Spring Cloud中,Feign常見問題總結SpringCloud
- 泛型類派生子類泛型
- Dubbo和Feign的區別?
- Feign實現動態URL
- Feign 注入失敗之坑