SpringBoot之统一数据返回格式的实现示例

 更新时间:2025年12月18日 08:30:29   作者:新绿MEHO  
本文主要介绍了SpringBoot之统一数据返回格式的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

之前我们实现的图书管理系统,函数的返回值格式都不统一,如果将这些函数的返回值格式都进行统一,将方便后续的返回和接收,但是如果我们挨个修改这些函数的返回值格式,有些麻烦,那么有没有别的好的办法呢?----有,就是下面我们要讲解的"SpringBoot之统一数据返回格式"。

统一数据返回格式

使用

统⼀的数据返回格式使⽤ @ControllerAdvice 和 ResponseBodyAdvice 的⽅式实现
@ControllerAdvice 表⽰控制器通知类。

定义类 ResponseAdvice , 实现 ResponseBodyAdvice 接⼝, 并在类上添加
@ControllerAdvice 注解。

@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {

    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        if (body instanceof Result){
            return body;
        }

        return Result.success(body);
    }
}

运行结果:

定义测试接口

@RequestMapping("/test")
@RestController
public class TestController {
    @RequestMapping("/t1")
    public String t1(){
        return "string";
    }

    @RequestMapping("/t2")
    public Integer t2(){
        return 1;
    }

    @RequestMapping("/t3")
    public Boolean t3(){
        return true;
    }

}

运行结果

t2返回结果:

t3返回结果:

t1返回结果:

为什么其他方法都能够正常返回,而返回类型为String时却不能正常返回,而且还抛出了ClassCastException异常,这是为什么呢?

问题解答(结合源码)

根据IDEA控制台打印的堆栈信息,我们首先看看StringHttpMessageConverter和AbstractHttpMessageConverter这两个类,特别是StringHttpMessageConverter的addDefaultHeaders方法和AbstractHttpMessageConverter的write方法,其中StringHttpMessageConverter是继承了AbstractHttpMessageConverter并重写了几个方法,特别是addDefaultHeaders方法,下面通过Debug方式运行:

再继续运行,会捕获到异常

由此我们知道,是因为返回结果为String类型的"string"被转换成了Result类型,但是在执行AbstractHttpMessageConverter的write方法时,因为AbstractHttpMessageConverter的派生类StringHttpMessageConverter重写了addDefaultHeaders方法,此时会调用StringHttpMessageConverter的addDefaultHeaders方法,但是StringHttpMessageConverter的addDefaultHeaders方法要求 t 的类型是String类型,但是无法从自定义的Result类型转换成String类型,因此抛出了ClassCastException异常。

那么问题来了,上面的三个测试接口,走的都是Result.success()方法,为什么却有不一样的结果,通过调试:

对于返回类型为String类型,在AbstractMessageConverterMethodProcessor里面的writeWithMessageConverters()方法时,在经过下图所示过程中,String类型会被转换成Result类型的结果,而且后面走的是StringHttpMessageConverter的addDefaultHeaders方法,其中StringHttpMessageConverter重写了AbstractHttpMessageConverter的addDefaultHeaders方法;

而返回值类型不是String类型时,经过和刚刚同样的步骤时,直接走的是AbstractHttpMessageConverter的addDefaultHeaders方法,而没有走StringHttpMessageConverter的addDefaultHeaders方法。

解决方法:对返回类型为String类型的字符串进行序列化

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import springbook.model.Result;

@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public boolean supports(MethodParameter returnType, Class converterType) {
        return true;
    }

    @SneakyThrows
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
        if (body instanceof Result){
            return body;
        }
        if (body instanceof String){
            return objectMapper.writeValueAsString(Result.success(body));
        }
        return Result.success(body);
    }
}

运行结果:

优点

1. ⽅便前端程序员更好的接收和解析后端数据接⼝返回的数据
2. 降低前端程序员和后端程序员的沟通成本, 按照某个格式实现就可以了, 因为所有接⼝都是这样返回的.
3. 有利于项⽬统⼀数据的维护和修改.
4. 有利于后端技术部⻔的统⼀规范的标准制定, 不会出现稀奇古怪的返回内容.

到此这篇关于SpringBoot之统一数据返回格式的实现示例的文章就介绍到这了,更多相关SpringBoot 统一数据返回格式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java shiro实现退出登陆清空缓存

    java shiro实现退出登陆清空缓存

    本篇文章主要介绍了java shiro实现退出登陆清空缓存,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-02-02
  • Springboot启动停止命令的.sh脚本编写方式

    Springboot启动停止命令的.sh脚本编写方式

    这篇文章主要介绍了Springboot启动停止命令的.sh脚本编写方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • 详解如何修改idea配置文件位置从C盘更改到D盘

    详解如何修改idea配置文件位置从C盘更改到D盘

    这篇文章主要给大家介绍了关于如何将idea的配置文件从默认的C盘调整到D盘,从而节省C盘使用空间,具有很好的参考价值,希望对大家有所帮助,需要的朋友可以参考下
    2023-10-10
  • 详解SpringBoot+SpringSecurity+jwt整合及初体验

    详解SpringBoot+SpringSecurity+jwt整合及初体验

    这篇文章主要介绍了详解SpringBoot+SpringSecurity+jwt整合及初体验,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-06-06
  • Java实现短信验证码的示例代码

    Java实现短信验证码的示例代码

    Java是一种流行的编程语言,验证码是一种常用的网络安全技术。Java发展至今,网上也出现了各种各样的验证码,下面是用Java实现短信验证码的总结,感兴趣的可以了解一下
    2023-03-03
  • Java子线程无法获取Attributes的解决方法(最新推荐)

    Java子线程无法获取Attributes的解决方法(最新推荐)

    在Java多线程编程中,子线程无法直接获取主线程设置的Attributes是一个常见问题,本文探讨了这一问题的原因,并提供了两种解决方案,对Java子线程无法获取Attributes的解决方案感兴趣的朋友一起看看吧
    2025-01-01
  • SpringBoot导入mail依赖报错问题解决

    SpringBoot导入mail依赖报错问题解决

    这篇文章主要介绍了SpringBoot导入mail依赖报错问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10
  • 浅析JAVA常用JDBC连接数据库的方法总结

    浅析JAVA常用JDBC连接数据库的方法总结

    本篇文章是对在JAVA中常用JDBC连接数据库的方法进行了详细的总结分析,需要的朋友参考下
    2013-07-07
  • IDEA连接postgressql数据库操作

    IDEA连接postgressql数据库操作

    这篇文章主要介绍了IDEA连接postgressql数据库操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • Java实现简单无界面五子棋

    Java实现简单无界面五子棋

    这篇文章主要为大家详细介绍了Java实现简单无界面五子棋,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05

最新评论