本文编码环境:springCloudAlibaba+openFeign+mybatisPlus2.0
最近在一个微服务项目中通过feign接口调用另一个微服务的查询所有接口是,将返回的集合数据封装到JsonResult的data中,然后在当前微服务中进行遍历取值。
发现会报一个错误
java.lang.ClassCastException Create breakpoint : java.util.LinkedHashMap cannot be cast to `xxx`
后来去了解了下feign大致的调用过程
Feign是一个声明式的Web Service客户端,它的目的就是让Web Service调用更加简单。Feign提供了HTTP请求的模板,通过编写简单的接口和插入注解,就可以定义好HTTP请求的参数、格式、地址等信息。而Feign则会完全代理HTTP请求,我们只需要像调用方法一样调用它就可以完成服务请求及相关处理。
feign调用的核心就是通过一系列的封装和处理,将以JAVA注解的方式定义的远程调用API接口,最终转换成HTTP的请求形式,然后将HTTP的请求的响应结果,解码成JAVA Bean,返回给调用者。Feign整合了Ribbon和RestTemplate,在使用RestTemplate调用后,底层进行json数据转换机制和@RestController(@ResponseBody)的转换机制不一样。
看到最后返回的是一个LinkedHashMap ,所以遍历的时候报错,LinkedHashMap 不能直接转换为自定义的对象。
想了解具体feign对于json数据的封装细节课参考:浅析RestTemplate的Jackson消息转换器_accept_empty_string_as_null_object_杨某人信了你的邪的博客-
因此我们在调用feign接口返回对象或者集合数据之后,要进行一个类型转换。
网上对于map转为对象的方法很多,这里我采用ObjectMapper进行反序列化。
使用它的convertValue方法,第一个参数是转换之前的数据,第二个参数是准备转成的目标类型。
再次运行,发现集合数据已经被转换成功:
然后就不会报错了。
除此之外呢,还可以使用JSON.parseObject,遍历先将每一个LinkedHashMap 转换为json字符串,在将json字符串转换成我们想要的数据类型。
该异常发现的所有代码如下:
//判断是否有填写了推荐码
if (referCode!=null || !referCode.equals("")){
//有推荐人
JSONResult jsonResult = saveLoginClient.getReferCodes();
List<ReferCode> referCodes = (List<ReferCode>) jsonResult.getData();
//进行反序列化
ObjectMapper mapper = new ObjectMapper();
List<ReferCode> referCodesNew = mapper.convertValue(referCodes, new TypeReference<List<ReferCode>>() {});
for (ReferCode r : referCodesNew) {
//如果对比所有推荐中有相同的
if (r.getCode().equals(referCode)){
//根据用户名查询UserBaseInfo对象,以获得用户id
Wrapper<User> query = new EntityWrapper<>();
User user = userService.selectOne(query.eq("nick_name", r.getUsername()));
userBaseInfo.setReferId(user.getId());
}
}
}