又踩到Feign坑了←_←(冷笑话)
问题复现
方法提供者,返回一个Result
对象,并将一个MemberVo
对象封装到了Result对象中的一个哈希表中:
@ApiOperation(value = "根据用户id获取信息")
@GetMapping("/member/{id}")
public Result getUserInfo(@PathVariable String id){
MemberVo loginInfoVo = memberService.getLoginInfo(id);
return Result.ok().data("item", loginInfoVo);
}
Result的结构:
public class Result {
private boolean flag;//是否成功
private Integer code;//返回码
private String message;//返回消息
private Map<String,Object> data = new HashMap<>();//返回数据
//...
}
Feign客户端:
@Component
@FeignClient(value = "service-ucenter",fallback = MemberFallback.class)
public interface MemberFeign {
@GetMapping("/ucenter/member/{id}")
public Result getUserInfo(@PathVariable String id);
}
Feign调用该方法,想从Result对象的哈希表中取出MemberVo
对象:
Result userInfo = memberFeign.getUserInfo(memberId);
MemberVo memberVo = (MemberVo) userInfo.getData().get("item");
就这两句话,看起来合情合理,我一开始也觉得应该没问题,结果报错:
java.util.LinkedHashMap cannot be cast to com.guli.ucenter.entity.vo.MemberVo
问题分析

调试发现,Feign调用后取到的Result对象的data已经不是一个HashMap了,而是一个LinkedHashMap
,里面存放的item对应的value,也变成了一个LinkedHashMap
,保留了原来MemberVo
对象的属性,但并不是一个MemberVo
对象。
原因其实不难想到,毕竟Feign调用的实质还是HTTP请求,中间还是经过了Json与对象的互转,转换过程中要进行对象关系映射,只能根据给它的类获取结构,而Result中data声明为一个Map接口,转换为LinkedHashMap也说得通,至于原来哈希表中的对象,根据Result类结构完全无法获知里面的哈希表中的数据到底是什么类型,当然也无法将它转换回原来的类对象。
可以猜测Feign会将Map接口(体现为json的object)和map中的对象(也体现为json中的object)都会转换为LinkedHashMap实例,至于为什么是LinkedHashMap而不是HashMap可能是为了维持键值对之间的顺序。
解决方案
关于解决方案,我想到的是,要么把LinkedHashMap当原来的类对象使用,毕竟也可以获取所有的属性和值;要么就专门为Feign调用设计一个方法,不要返回嵌套Map的Result对象;要么就将LinkedHashMap转为原来的类对象。
最后我选择了专门为Feign调用设计一个方法?
原创文章,作者:彭晨涛,如若转载,请注明出处:https://www.codetool.top/article/%e5%85%b3%e4%ba%8efeign%e8%b0%83%e7%94%a8%e4%bc%9a%e5%b0%86%e5%af%b9%e8%b1%a1%e5%b5%8c%e5%a5%97%e7%9a%84map%e8%bd%ac%e4%b8%balinkedhashmap%e7%9a%84%e9%97%ae%e9%a2%98/