在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---->反序列化

实现步骤:

  1. 服务提供方返回泛型类型的全限定名 如com.csdn.product.Goods 可放在header中
  2. 客户端继承Decoder 接口,重写decode方法。
  3. 得到类名后和response数据.
  4. 通过反射实例化Goods,得到Goods 的Class类
  5. 通过反序列化,得到Goods 类实例,
  6. 然后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;
    }
}
  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值