目录
- 前言
- 分析原因
- 解决方案一
- 解决方案二
- 解决方案三
- 总结
前言
之前文章中介绍了如何设计API接口,实现统一格式返回?,最后章节中谈到优雅方案,利用ResponseBodyAdive方案,进行返回体包装;但在使用过程中发现如果方法返回String类型时,就会报错
java.lang.ClassCastException: com.xxxx.dto.common.ResponseResult cannot be cast to java.lang.String
我们来看一下怎么解决?
分析原因
我们通过封装后返回的就是转换json格式的数据,为何报了类型转换异常?为什么这个对象要转换成String呢?然后报了cannot be cast to java.lang.String错误。
我们debug一下:
我们看到,这里所选的类型转换器是"org.springframework.http.converter.StringHttpMessageConverter",至此我们再看如果返回其他类型看看这里选择的是何种转换器呢?
将返回值类型改为int后,可以发现mvc框架选中的转换器是org.springframework.http.converter.json.MappingJackson2HttpMessageConverter。
那么问题是找到了,返回字符串的时候采用的是特殊的StringHttpMessageConverter转换器,而其他格式则是采用MappingJackson2HttpMessageConverter转换器来解析的。
StringHttpMessageConverter转换器将内容转为String字符串,而当前我们返回的则是一个具体的对象,这就导致了报错的根本原因也就是类型转换异常。
问题的根因找到了,那我们怎么去解决?
解决方案一
我们知道了String类型会用StringHttpMessageConverter进行处理,其他的类型用MappingJackson2HttpMessageConverter处理,那我们是不是也可以把String类型也用MappingJackson2HttpMessageConverter处理呢。
那我们可以提升优先级
@Configuration
public class WebConfiguration implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.add(0, new MappingJackson2HttpMessageConverter());
}
}
解决方案二
我们也可以去除StringHttpMessageConverter
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
// add方法可以指定顺序,有多个自定义的WebMvcConfigurerAdapter时,可以改变相互之间的顺序
// 但是都在springmvc内置的converter前面
ArrayList<HttpMessageConverter<?>> objects = new ArrayList<>();
for (HttpMessageConverter<?> converter : converters) {
if (converter.getClass().isAssignableFrom(StringHttpMessageConverter.class)) {
objects.add(converter);
}
}
converters.removeAll(objects);
}
解决方案三
我们可以在转换的时候,判断一下String类型
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType,
MediaType selectedContentType, Class selectedConverterType,
ServerHttpRequest request, ServerHttpResponse response) {
//当返回类型是String时,用的是StringHttpMessageConverter转换器,无法转换为Json格式
//必须在方法体上标注RequestMapping(produces = "application/json; charset=UTF-8")
if(body instanceof String){
String str = JSON.toJSONString(Result.success(body));
return str;
}
return Result.success(body);
}
总结
之前留的坑,到现在才来总结,小伙伴们之前有没有碰到过,有没有尝试去解决呢?如果自己已经解决了,说明你自身的要求比较高哦。谢谢!!!
推荐阅读
Spring多种启动初始化方案,看这篇就够了
来说说ThreadLocal内存溢出问题
阿里面试题:强、软、弱、虚引用的特点及应用场景
企业常用的并发编程Queue的源码分析
了解JAVA中的SPI机制,以及数据库驱动插件,这一篇就够了
企业实战之阿里druid统一监控方案,你了解吗?
千人千面精准推荐之大白话讲解协同算法(一),看这篇就够了
企业实战之分布式锁方案一步步的演变
你了解滑动时间窗口吗?Sentinel核心源码剖析
Sentinel全局Feign默认熔断降级策略的思考
你所不知道的头部参数传递的坑,来吧!抓紧出坑
5分钟让你理解K8S必备架构概念,以及网络模型(一)
5分钟让你理解K8S必备架构概念,以及网络模型(二)
5分钟让你理解K8S必备架构概念,以及网络模型(三)
大厂如何基于binlog解决多机房同步mysql数据(一)?
大厂如何基于binlog解决多机房同步mysql数据(二)?
基于binlog的canal组件有哪些使用场景(三)?
基于binlog日志之canal企业应用及高可用原理(四)?
可用于大型应用的微服务生态灰度发布如何实现?
一线大厂级别公共Redis集群监控,细化到每个项目实例
Sharding-jdbc的实战入门之水平分表(一)
Sharding-Jdbc之水平分库和读写分离(二)