SpringBoot统一返回类型之String

219 阅读2分钟

sp.jpg 持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情


前两天在使用 Spring拦截器 做一个统一返回类型处理的时候,出了一个问题:

java.lang.ClassCastException: java.util.HashMap cannot be cast to java.lang.String

通过上面的异常信息,我们可以知道它的意思是:无法将 HashMap 转化成 String

我反复查看了几遍代码,确定我并没有去写这种的转换代码。

通过打断点的方式,终于确定了问题出现的地方: image.png

image.png 在调试中可以看到,直到当前,程序都没有问题。并且 map 里存放的也是我想要的东西,但是如果继续运行,就会抛出一个上面的异常。

这时问题的所在就可以确定了: 我在自定义拦截器中重写 beforeBodyWrite 方法时,Object body 从 controller 层接收的是一个 String。而默认的 StringHttpMessageConverter转换器 并不能将 String 转换成一个 json类型。这时如果不对 String 手动处理,在将 beforeBodyWrite 这个回调函数交给接口调用的时候,就会出现异常


怎么解决?

我的思路:

  1. 避开这个坑,不要单纯的返回一个 String。可以通过一个 Map/自定义Result类 进行封装(controller层时封装)。

网上的解决思路:

  1. 添加一个 json转换器,这样源码在处理 String 时,就不会按照原先的处理方式去进行。而是会调用我们提供的这个 json转换器 来去处理。
//添加 json 格式转换器 ——》 用来处理 SpringBoot 中 统一返回类型时 controller 直接返回一个 String 的情况
@SpringBootApplication
public class Application {
    @Bean
    public HttpMessageConverters converters() {
        return new HttpMessageConverters(
                false, Arrays.asList(new MappingJackson2HttpMessageConverter()));
    }
}
  1. 在拦截器中直接封装一个方法,专门用来对 String 类型进行处理。
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType,
                                                   MediaType selectedContentType,
                                                   Class selectedConverterType,
                                                   ServerHttpRequest request,
                                                   ServerHttpResponse response) {

        Object obj = null;
        // 通过判断是否是一个 String 类型来决定是否有错误信息
        if(body instanceof String){
            // Result 为自定义类型,用来对 body 数据进行包裹
            obj = Result.fail(body);
            return toJson(obj);
        }else{
            obj = Result.success(body);
        }
        return obj;
    }

    private Object toJson(Object response){
        try {
            // 通过 jackson 来将对象转换成一个 json 格式的字符串
            return new ObjectMapper().writeValueAsString(response);
        } catch (JsonProcessingException e) {
            // 表示转换不了
            e.printStackTrace();
        }
        return null;
    }
// 自定义响应数据类型
@Data
public class Result{
    private int status;      // 表示通讯是否成功
    private String msg;      // 响应信息
    private Object data;     // 响应数据

    private Result(){
    }

    public static Result success(Object data){
        Result result = new Result();
        result.setStatus(1);
        result.setMsg("");
        result.setData(data);
        return result;
    }

    public static Result fail(Object msg){
        String str = msg.toString();
        Result result = new Result();
        result.setStatus(0);
        result.setMsg(str);
        result.setData("");
        return result;
    }
}

总结:
问题不是很难,解决办法也有好几种。通过比较,发现使用 json转换器来处理,更加简单明了。并且这个也是固定写法,不用更改。直接 cv 大法即可。

记录日常出现的问题。既加深了印象,又有利于复习回顾!