当前位置: 首页 > article >正文

Spring Boot 统一返回数据格式

  在构建 RESTful API 时,保持一致的返回数据格式至关重要。统一的返回格式不仅可以提高 API 的可读性,还能方便客户端解析和处理响应数据。Spring Boot 提供了多种方式来实现统一的返回数据格式,本文将深入探讨如何在 Spring Boot 项目中实现这一目标,并提供代码示例和最佳实践。

为什么需要统一的返回数据格式?

  1. 提高 API 可读性: 统一的格式可以让客户端更容易理解 API 的响应数据。
  2. 简化客户端解析:客户端可以编写更简单的代码来解析和处理响应数据,无需处理各种不同的数据结构。
  3. 方便错误处理:统一的格式可以方便客户端识别错误,并根据错误代码进行相应处理。
  4. 提升 API 的整体质量: 一致的数据格式是良好 API设计的基本要素,可以提高 API 的整体质量和易用性。
  5. 方便前后端协同: 统一的数据格式可以减少前后端开发人员在数据对接过程中的沟通成本,提高开发效率。

Spring Boot 中实现统一返回数据格式的思路

  在 Spring Boot 中,实现统一的返回数据格式,通常采用以下步骤:

1.定义统一的响应体结构: 创建一个 Java 类,用于表示统一的响应体结构,该结构通常包含:
code: 表示响应状态码,例如成功、失败、参数错误等。
message: 表示响应消息,用于描述请求结果。
data: 表示响应数据,用于返回实际的数据内容。
timestamp: (可选) 返回时间戳。

2.创建统一的响应类:创建一个工具类,用于创建具有统一格式的响应对象。
使用 @RestControllerAdvice@ResponseBodyAdvice 进行全局处理:
使用 @RestControllerAdvice 注解可以拦截所有 @RestController 中的响应,并修改响应数据。
使用 @ResponseBodyAdvice 注解也可以拦截响应,但是需要配合 @Controller 使用。

实践:创建统一的响应数据格式

1.定义统一的响应体结构

@ApiModel("响应结果")
@Data
public class Result<T> extends BaseObject{

    /**
     * code
     */
    @ApiModelProperty(value = "响应代码")
    private Integer code;

    /**
     * message
     */
    @ApiModelProperty(value = "响应消息")
    private String msg;

    /**
     * data
     */
    @ApiModelProperty(value = "数据结果")
    private T data;

    public Result() {
    }

    public Result(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    private Result(T data) {
        this.code  = Status.SUCCESS.getCode();
        this.data = data;
    }

    private Result(Status status) {
        if (status != null) {
            this.code = status.getCode();
            this.msg = status.getMsg();
        }
    }

    public Result(Integer code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    /**
     * Call this function if there is success
     * @param data data
     * @param <T> type
     * @return resule
     */
    public static <T> Result<T> success(T data) {
        return new Result<>(data);
    }

    /**
     * 返回错误消息
     * @return
     */
    public static Result error()
    {
        return Result.error("操作失败");
    }

    /**
     * 返回错误消息
     * @param msg 返回内容
     * @return 警告消息
     */
    public static Result error(String msg)
    {
        return Result.error(msg, null);
    }

}

2.定义响应枚举 (ResultCode):

public enum Status {

    //成功
    SUCCESS(0, "success", "成功"),
    //系统异常
    SYSTEM_EXCEPTION(10000, "system exception", "系统异常"),
    //业务异常
    SERVICE_EXCEPTION(10001, "service exception", "业务异常")
    ;

    private final int code;
    private final String enMsg;
    private final String zhMsg;

    private Status(int code, String enMsg, String zhMsg) {
        this.code = code;
        this.enMsg = enMsg;
        this.zhMsg = zhMsg;
    }

    public int getCode() {
        return this.code;
    }

    public String getMsg() {
        if (Locale.SIMPLIFIED_CHINESE.getLanguage().equals(LocaleContextHolder.getLocale().getLanguage())) {
            return this.zhMsg;
        } else {
            return this.enMsg;
        }
    }
}

3.定义全局统一响应处理类(可选):

@ControllerAdvice
public class CustomerResponseAdvice implements ResponseBodyAdvice<Object> {


    @Override
    public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object o, MethodParameter methodParameter, MediaType mediaType, Class<? extends HttpMessageConverter<?>> aClass, ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse) {
        return o;
    }

}
  1. 使用 @RestControllerAdvice 注解声明该类为全局响应处理类。
  2. 实现了 ResponseBodyAdvice 接口,可以拦截所有的响应。
  3. beforeBodyWrite 方法中,将返回数据包装成 Result 对象。
  4. supports方法判断是否需要拦截,这里通过判断包名进行拦截。

4.在 Controller 中直接返回业务数据

@RestController
@RequestMapping("/yes")
public class ExtendController extends BaseController {

    @Autowired
    private UserInfoService userInfoService;

    @PostMapping("/list")
    public Result<PageDataInfo<UserInfo>> queryUserInfoList(@RequestBody UserInfoReq req) {
        startPage(req);
        return Result.success(buildPageDataInfo(userInfoService.list()));
    }

}

5.测试统一响应格式

{
    "code": 0,
    "msg": null,
    "data": {
        "total": 5,
        "list": [
            {
                "id": 1,
                "name": "test02",
                "password": "test02",
                "age": 1,
                "status": 1,
                "lastLoginTime": null,
                "token": null,
                "createTime": "2022-06-21 17:57:14",
                "updateTime": "2022-06-21 17:57:16"
            }
        ],
        "statObj": null
    }
}

最佳实践

  1. 使用枚举管理状态码: 使用枚举 (ResultCode) 来管理状态码,避免使用 Magic Number,提高代码可读性和可维护性。
  2. 提供更友好的错误提示: 在全局异常处理中,使用 Result 对象返回更友好的错误提示信息,方便客户端处理。
  3. 考虑使用 AOP:可以使用 AOP (面向切面编程)来统一处理返回格式,减少代码重复。
  4. 灵活控制返回格式:可以根据实际需求,添加更多的字段,例如分页信息,响应时间等等。

http://www.kler.cn/a/507009.html

相关文章:

  • GraphRAG如何使用ollama提供的llm model 和Embedding model服务构建本地知识库
  • Kafka权威指南(第2版)读书笔记
  • Vulnhub DC-8靶机攻击实战(一)
  • vue3+elementPlus之后台管理系统(从0到1)(day1)
  • HarmonyOS Next 实现登录注册页面(ARKTS) 并使用Springboot作为后端提供接口
  • 【编译构建】用cmake编译libjpeg动态库并实现转灰度图片
  • 【2025最新版】PCL点云处理算法汇总(C++长期更新版)
  • 从零深度学习:(2)最小二乘法
  • 网安——CSS
  • [Linux]——进程(2)
  • “AI智能服务平台系统,让生活更便捷、更智能
  • list的模拟实现详解
  • 核心前端技术详解
  • Jupyter notebook中运行dos指令运行方法
  • Java进阶-在Ubuntu上部署SpringBoot应用
  • 微软开源AI Agent AutoGen 详解
  • Docker部署Spring Boot + Vue项目
  • ParcelFileDescriptor+PdfRenderer在Android渲染显示PDF文件
  • Spring Boot中使用AOP实现权限管理
  • Python 的时间处理模块 datetime 详解
  • 图论1-问题 B: 算法7-4,7-5:图的遍历——深度优先搜索
  • 博图 linucx vmware
  • css 实现自定义虚线
  • QT 通过QAxObject与本地应用程序读取Excel内容
  • 汽车故障码U100187 LIN1Communication time out 解析和处理方法
  • 【50个服务器常见端口】