如何优美地设计springboot接口返回

656人浏览 / 0人评论 / 添加收藏

前言:

       开发过程中接口数据的交互总是不可避免,数据返回的格式虽说没有统一规定,但是一些优美的接口返回总是会给予一些好的体验。

1. 数据返回通用格式

public class ResultBean<T> {
   private Integer code;
   private String message;
   private T data;
}
code :状态码,常见的 200,404 这些,常规的状态码可能会不够用,几乎稍微大点的项目都会自定义,这块的声明一般会和message一起用枚举实现。

message:提示信息,是对code的一种补充说明。

data:数据结构体,这块跟业务强相关,除了要求满足 json 格式外没有特殊的约定。

2. 枚举声明状态码和提示信息

上面提到 code 和 message 一般会用枚举实现,下面展示一下(实际过程中远不止下面三种情况):

package com.test.result;

public enum ResultCode {

   SUCCESS(200, "成功"),
   PARAM_INVALID(402, "参数输入错误"),
   UNKNOWN_ERROR(500, "未知错误");

   private Integer code;
   private String message;

   ResultCode(Integer code, String message) {
       this.code = code;
       this.message = message;
   }

   public Integer getCode() {
       return code;
   }

   public void setCode(Integer code) {
       this.code = code;
   }

   public String getMessage() {
       return message;
   }

   public void setMessage(String message) {
       this.message = message;
   }

}

3. 数据返回格式函数补充

步骤 1 中的数据返回结构体需要补充一些常用的方法才能继续使用

public class ResultBean<T> {

   private Integer code;
   private String message;
   private T data;

   ResultBean() {
   }

   // 返回成功
   public static <T> ResultBean<T> success() {
       ResultBean<T> resultBean = new ResultBean<>();
       resultBean.setCode(ResultCode.SUCCESS.getCode());
       resultBean.setMessage(ResultCode.SUCCESS.getMessage());
       return resultBean;
   }

   // 返回成功
   public static <T> ResultBean<T> success(T result) {
       ResultBean<T> resultBean = ResultBean.success();
       resultBean.setData(result);
       return resultBean;
   }

   // 返回失败
   public static <T> ResultBean<T> error() {
       ResultBean<T> resultBean = new ResultBean<>();
       resultBean.setCode(ResultCode.UNKNOWN_ERROR.getCode());
       resultBean.setMessage(ResultCode.UNKNOWN_ERROR.getMessage());
       return resultBean;
   }

   // 返回失败
   public static <T> ResultBean<T> error(T result) {
       ResultBean<T> resultBean = ResultBean.success();
       resultBean.setData(result);
       return resultBean;
   }

   // 自定义方法,留作扩展
   public static <T> ResultBean<T> defined(Integer code, String message, T result) {
       ResultBean<T> resultBean = new ResultBean<>();
       resultBean.setCode(code);
       resultBean.setMessage(message);
       resultBean.setData(result);
       return resultBean;
   }


   public Integer getCode() {
       return code;
   }

   public void setCode(Integer code) {
       this.code = code;
   }

   public String getMessage() {
       return message;
   }

   public void setMessage(String message) {
       this.message = message;
   }

   public T getData() {
       return data;
   }

   public void setData(T data) {
       this.data = data;
   }
}

4. 模拟实际使用场景

声明一个数据存储的类 Data:

public class Data {

   private Integer id;
   private String info;

   public Integer getId() {
       return id;
   }

   public void setId(Integer id) {
       this.id = id;
   }

   public String getInfo() {
       return info;
   }

   public void setInfo(String info) {
       this.info = info;
   }
}

写一个调用接口:

   @GetMapping("/result")
   public ResultBean test() {
       Data data = new Data();
       data.setId(111);
       data.setInfo("this is a test data");
       return ResultBean.success(data);
   }
测试结果不展示了。

5. 进阶

       日志系统有一个字段 requestId,这个 id 是用来回溯请求的,为了方便定位接口问题一般也会把这个字段加到返回结构体里面,可以参考 logback + MDC 搭建 springboot 的日志系统,日志系统搭建好了的话,改造其实很简单,ResultBean 里面加一个字段 requestId,同时在构造方法里面获取该字段即可:

public class ResultBean<T> {

   private String requestId;
   private Integer code;
   private String message;
   private T data;

   ResultBean() {
       this.requestId = RequestIdUtil.getRequestId();
   }

   // 返回成功
   public static <T> ResultBean<T> success() {
       ResultBean<T> resultBean = new ResultBean<>();
       resultBean.setCode(ResultCode.SUCCESS.getCode());

       resultBean.setMessage(ResultCode.SUCCESS.getMessage());
       return resultBean;
   }

   // 返回成功
   public static <T> ResultBean<T> success(T result) {
       ResultBean<T> resultBean = ResultBean.success();
       resultBean.setData(result);
       return resultBean;
   }

   // 返回失败
   public static <T> ResultBean<T> error() {
       ResultBean<T> resultBean = new ResultBean<>();
       resultBean.setCode(ResultCode.UNKNOWN_ERROR.getCode());
       resultBean.setMessage(ResultCode.UNKNOWN_ERROR.getMessage());
       return resultBean;
   }

   // 返回失败
   public static <T> ResultBean<T> error(T result) {
       ResultBean<T> resultBean = ResultBean.success();
       resultBean.setData(result);
       return resultBean;
   }

   // 自定义方法,留作扩展
   public static <T> ResultBean<T> defined(Integer code, String message, T result) {
       ResultBean<T> resultBean = new ResultBean<>();
       resultBean.setCode(code);
       resultBean.setMessage(message);
       resultBean.setData(result);
       return resultBean;
   }

   public String getRequestId() {
       return requestId;
   }

   public void setRequestId(String requestId) {
       this.requestId = requestId;
   }

   public Integer getCode() {
       return code;
   }

   public void setCode(Integer code) {
       this.code = code;
   }

   public String getMessage() {
       return message;
   }

   public void setMessage(String message) {
       this.message = message;
   }

   public T getData() {
       return data;
   }

   public void setData(T data) {
       this.data = data;
   }

}

全部评论