专栏名称: 终码一生
提供免费JB账号,激活码,破解工具下载;分享Java开发技术(JVM,多线程,高并发,性能调优),开源项目,常见开发问题和前沿科技资讯等!
目录
相关文章推荐
新疆是个好地方  ·  乌鲁木齐,local又洋气 ·  昨天  
新疆是个好地方  ·  乌鲁木齐,local又洋气 ·  昨天  
常观  ·  ye~常州欢迎宁🤟🤟🤟 ·  昨天  
常观  ·  ye~常州欢迎宁🤟🤟🤟 ·  昨天  
天津市文化和旅游局  ·  早安·天津 ·  昨天  
衡阳日报  ·  冲冲冲!衡阳这个热门景区门票有变化 ·  2 天前  
安徽省人民政府网  ·  蚌埠双墩遗址入选国家考古遗址公园 ·  3 天前  
安徽省人民政府网  ·  蚌埠双墩遗址入选国家考古遗址公园 ·  3 天前  
51好读  ›  专栏  ›  终码一生

Controller层代码瘦身70%!5招打通任督二脉,效率飙升

终码一生  · 公众号  ·  · 2025-06-05 22:45

正文

请到「今天看啥」查看全文


supports (MethodParameter returnType, Class extends HttpMessageConverter>> converterType) ;

@Nullable
T beforeBodyWrite (@Nullable T body, MethodParameter returnType, MediaType selectedContentType, Class extends HttpMessageConverter>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) ;
}
  • supports: 判断是否要交给 beforeBodyWrite 方法执行,ture:需要;false:不需要

  • beforeBodyWrite: 对 response 进行具体的处理。

// 如果引入了swagger或knife4j的文档生成组件,这里需要仅扫描自己项目的包,否则文档无法正常生成
@RestControllerAdvice(basePackages = "com.example.demo")
publicclassResponseAdviceimplementsResponseBodyAdvice<Object{
    @Override
    publicbooleansupports(MethodParameter returnType, Class extends HttpMessageConverter>> converterType){
        // 如果不需要进行封装的,可以添加一些校验手段,比如添加标记排除的注解
        returntrue;
    }


    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class extends HttpMessageConverter>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response){
        // 提供一定的灵活度,如果body已经被包装了,就不进行包装
        if (body instanceof Result) {
            return body;
        }
        return Result.success(body);
    }
}

经过这样改造,既能实现对 Controller 返回的数据进行统一包装,又不需要对原有代码进行大量的改动。

处理 cannot be cast to java.lang.String 问题

如果直接使用 ResponseBodyAdvice ,对于一般的类型都没有问题,当处理字符串类型时,会抛出 xxx.包装类 cannot be cast to java.lang.String 的类型转换的异常。

ResponseBodyAdvice 实现类中 debug 发现,只有 String 类型的 selectedConverterType 参数值是 org.springframework.http.converter.StringHttpMessageConverter ,而其他数据类型的值是 org.springframework.http.converter.json.MappingJackson2HttpMessageConverter

  • String 类型
图片
  • 其他类型 (如 Integer 类型)
图片

现在问题已经较为清晰了,因为我们需要返回一个 Result 对象。

所以使用 MappingJackson2HttpMessageConverter 是可以正常转换的。

而使用 StringHttpMessageConverter 字符串转换器会导致类型转换失败。

现在处理这个问题有两种方式:

①在 beforeBodyWrite 方法处进行判断,如果返回值是 String 类型就对 Result 对象手动进行转换成 JSON 字符串,另外方便前端使用,最好在 @RequestMapping 中指定 ContentType

@RestControllerAdvice(basePackages = "com.example.demo")
publicclassResponseAdviceimplementsResponseBodyAdvice<Object{
    ...
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class extends HttpMessageConverter>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response){
        // 提供一定的灵活度,如果body已经被包装了,就不进行包装
        if (body instanceof Result) {
            return body;
        }
        // 如果返回值是String类型,那就手动把Result对象转换成JSON字符串
        if (body instanceof String) {
            try {
                returnthis.objectMapper.writeValueAsString(Result.success(body));
            } catch (JsonProcessingException e) {
                thrownew RuntimeException(e);
            }
        }
        return Result.success(body);
    }
    ...
}

@GetMapping(value = "/returnString", produces = "application/json; charset=UTF-8")
public String returnString(){
    return"success";
}

②修改 HttpMessageConverter 实例集合中 MappingJackson2HttpMessageConverter 的顺序。因为发生上述问题的根源所在是集合中 StringHttpMessageConverter 的顺序先于 MappingJackson2HttpMessageConverter 的,调整顺序后即可从根源上解决这个问题。

网上有不少做法是直接在集合中第一位添加 MappingJackson2HttpMessageConverter







请到「今天看啥」查看全文


推荐文章
新疆是个好地方  ·  乌鲁木齐,local又洋气
昨天
新疆是个好地方  ·  乌鲁木齐,local又洋气
昨天
常观  ·  ye~常州欢迎宁🤟🤟🤟
昨天
常观  ·  ye~常州欢迎宁🤟🤟🤟
昨天
天津市文化和旅游局  ·  早安·天津
昨天
安徽省人民政府网  ·  蚌埠双墩遗址入选国家考古遗址公园
3 天前
安徽省人民政府网  ·  蚌埠双墩遗址入选国家考古遗址公园
3 天前
上海天气发布  ·  明日“处暑” 爽秋还在路上
7 年前