四时宝库

程序员的知识宝库

解决Api统一格式返回,遗留地返回String一个问题

目录

  1. 前言
  2. 分析原因
  3. 解决方案一
  4. 解决方案二
  5. 解决方案三
  6. 总结

前言

之前文章中介绍了如何设计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);
}

总结

之前留的坑,到现在才来总结,小伙伴们之前有没有碰到过,有没有尝试去解决呢?如果自己已经解决了,说明你自身的要求比较高哦。谢谢!!!


推荐阅读

SpringMVC全局异常方案、源码分析,以及常见的入坑

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之水平分库和读写分离(二)

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接