问题:为啥调用rpc远程服务后,返回的响应类的结果无法向下转型?具体报错
java.util.LinkedHashMap cannot be cast to com.huibo.framework.domain.ucenter.ext.AdminLite
java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.huibo.framework.domain.ucenter.ext.AdminLite
有博主说关于springcloud中使用feign出现LinkedHashMap can not be cast to xxx 的问题是因为:feign默认是根据返回的数据解析为LinkedHashMap这种key value的格式,但是我们项目中一般会有自定义的Result<T,E>这样的复杂类型的对象,这样的话,feign就不能像dubbo这样的rpc那样得到我们自己想要的Result<T,E>对象。
解决用 自定义FeignClient,覆盖提供的FeignClient。我觉得不一定有用,但是用使用fastjson将对象和字符串进行转换就可以恢复原样,不过太消耗性能。
@Configuration
public class FeignConfig {
@Bean
public Decoder feignDecoder() {
HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(objectMapper());
ObjectFactory<HttpMessageConverters> objectFactory = () -> new HttpMessageConverters(jacksonConverter);
return new ResponseEntityDecoder(new SpringDecoder(objectFactory));
}
@Bean
public Encoder feignEncoder(){
HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(objectMapper());
ObjectFactory<HttpMessageConverters> objectFactory = () -> new HttpMessageConverters(jacksonConverter);
return new SpringEncoder(objectFactory);
}
public ObjectMapper objectMapper(){
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
return objectMapper;
}
}
// 将对象转换成为字符串
String str = JSON.toJSONString(infoDo);
// 将字符串转换成为对象
InfoDo infoDo = JSON.parseObject(strInfoDo, InfoDo.class);
// 将对象集合转换成为字符串
String users = JSON.toJSONString(users);
//将字符串转换成为对象集合
List<User> userList = JSON.parseArray(userStr, User.class);
都说是feign的问题,但是SpringCloud 复杂对象接收时候对象变成LinkeHashMap。通过使用泛型参数,实际类型信息完全丢失到运行时并且无法推断。它本质上最终是相同的
Object
。当Gson发现你想要一个Object
类型时,它使用aMap
来放置JSON信息。这样,如果你重新序列化该对象实例,数据将被保留。所以在定义接口的时候返回的泛型必须确定。其中BaseResult的范性应该为List<UserVO> ,如果没有写,那么返回的结果就会变成List<LinkedHashMap>,这样就导致一些去参数错误。
// 错误实例
@PostMapping("/user/queryUserByAccountStatus")
BaseResult queryUserByAccountStatus(@RequestBody AccountsTenantIdStatusArg arg);
// 正确实例
@PostMapping("/user/queryUserByAccountStatus")
BaseResult<List<UserVO>> queryUserByAccountStatus(@RequestBody AccountsTenantIdStatusArg arg);