本文编码环境:springCloudAlibaba+openFeign+mybatisPlus2.0

最近在一个微服务项目中通过feign接口调用另一个微服务的查询所有接口是,将返回的集合数据封装到JsonResult的data中,然后在当前微服务中进行遍历取值。

java feign RequestInterceptor 拦截器_微服务

 发现会报一个错误

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)的转换机制不一样。

java feign RequestInterceptor 拦截器_List_02

 看到最后返回的是一个LinkedHashMap ,所以遍历的时候报错,LinkedHashMap 不能直接转换为自定义的对象。

想了解具体feign对于json数据的封装细节课参考:浅析RestTemplate的Jackson消息转换器_accept_empty_string_as_null_object_杨某人信了你的邪的博客-

 因此我们在调用feign接口返回对象或者集合数据之后,要进行一个类型转换。

网上对于map转为对象的方法很多,这里我采用ObjectMapper进行反序列化。

java feign RequestInterceptor 拦截器_开发语言_03

 使用它的convertValue方法,第一个参数是转换之前的数据,第二个参数是准备转成的目标类型。

java feign RequestInterceptor 拦截器_java_04

 再次运行,发现集合数据已经被转换成功:

java feign RequestInterceptor 拦截器_java_05

java feign RequestInterceptor 拦截器_java_06

然后就不会报错了。 

除此之外呢,还可以使用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());
                }
            }
        }