【SpringCloud-Feign】SpringCloud项目通过fegin远程调用接口返回结果类型为LinkedHashMap

项目场景:

SpringCloud项目通过fegin远程调用接口返回结果类型转换失败。


问题描述

SpringCloude项目通过fegin远程调用接口返回linkedHashMap,导致报错java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.xx.xx.xx.model.xxBean
具体操作流程为:

  1. A服务提供外部查询接口,调用接口时将结果对象序列化存到redis中;
  2. B服务通过feign调用A接口,获取结果,然后将结果转换为想要的bean对象;
  3. B调用接口返回报错类型转换失败;

A服务接口实现:

【SpringCloud-Feign】SpringCloud项目通过fegin远程调用接口返回结果类型为LinkedHashMap_第1张图片

原因分析:

  1. 通过debug发现通过feign方法调用返回结果是LinkedHashMap类型,导致类型转换失败,如下图:

接口调用:
【SpringCloud-Feign】SpringCloud项目通过fegin远程调用接口返回结果类型为LinkedHashMap_第2张图片
返回结果:
【SpringCloud-Feign】SpringCloud项目通过fegin远程调用接口返回结果类型为LinkedHashMap_第3张图片

转换过程:
【SpringCloud-Feign】SpringCloud项目通过fegin远程调用接口返回结果类型为LinkedHashMap_第4张图片
2. 转换为具体的Bean对象时导致无法转换;
3. 原因:

1 、Spring Cloud中,当使用Feign客户端进行服务间远程调用时,可能会出现接口调用方期望得到一个特定的对象类型,但实际上收到的确实java.util.LinkedHashMap类型的情况。这出现的原因主要和Java泛型在运行时的类型擦除以及远程HTTP响应的序列化/反序列化机制有关
2、在Java中,泛型信息在编译时会进行类型擦除,只有原始类型会保留下来。当Feign客户端接收到远程服务的HTTP响应时,因为泛型信息已经不存在,所以Feign的解码器(默认使用Jackson或Gson)会将JSON响应转换成最接近的映射类型,也就是LinkedHashMap,特别是当它不确定具体应该转换为哪种Java对象类型时。
3、LinkedHashMap是Java中的一种实现了Map接口的类,它继承自HashMap,并且保持了元素的插入顺序。因此,使用LinkedHashMap作为默认的返回结果类型可以保留远程接口返回数据的顺序。

另一种说法:

因为rpc远程调用在底层还是使用的HTTPClient,所以在传递参数的时候,必定要有个顺序,当你传递map的时候map里面的值也要有顺序,不然服务层在接的时候就出问题了,所以它才会从map转为linkedhashMap!spring 有一个类叫ModelMap,继承了linkedhashMap ,所以一个接口返回的结果就可以直接用ModelMap来接,注意ModelMap是没有泛型的,不管你返回的结果是什么类型的map,泛型是多复杂的map,都可以直接new一个Modelmap,用它来接返回的结果。


解决方案:

  1. 调用外部服务获取结果后,对结果进行加工处理,对返回结果进行map转bean处理,比较笨。
    【SpringCloud-Feign】SpringCloud项目通过fegin远程调用接口返回结果类型为LinkedHashMap_第5张图片
  2. 使用具体的类代替泛型类型:在Feign客户端的接口定义中,使用具体的类代替泛型。这样可以避免由于类型擦除导致的问题。
  3. 自定义编解码器:提供自定义的JSON编解码器,这样可以在反序列化时指定确切的类型。
  4. 容错处理:可以在客户端逻辑中增加对LinkedHashMap的处理,使得代码可以灵活处理不同的返回类型。

可根据项目实际情况选择合适的处理方式!!!

你可能感兴趣的:(spring,cloud,spring,后端)