1.自定义枚举类
public enum ReturnCode {
RC200(200, "ok"),
RC400(400, "请求失败,参数错误,请检查后重试。"),
RC404(404, "未找到您请求的资源。"),
RC405(405, "请求方式错误,请检查后重试。"),
RC500(500, "操作失败,服务器繁忙或服务器错误,请稍后再试。");
// 自定义状态码
private final int code;
// 自定义描述
private final String msg;
ReturnCode(int code, String msg) {
this.code = code;
this.msg = msg;
}
public int getCode() {
return code;
}
public String getMsg() {
return msg;
}
}
该枚举类为我们和前端约定好的返回状态码和描述信息,可根据自己的需求修改状态码和描述
2.自定义统一返回格式类
@Data
public class R<T> {
private Integer code; //状态码
private String msg; //提示信息
private T data; //数据
private long timestamp;//接口请求时间
public R() {
this.timestamp = System.currentTimeMillis();
}
public static <T> R<T> success(T data) {
R<T> r = new R<>();
r.setCode(ReturnCode.RC200.getCode());
r.setMsg(ReturnCode.RC200.getMsg());
r.setData(data);
return r;
}
public static <T> R<T> error(int code, String msg) {
R<T> r = new R<>();
r.setCode(code);
r.setMsg(msg);
r.setData(null);
return r;
}
}
@Data
注解为Lombok工具类库中的注解,提供类的get、set、equals、hashCode、canEqual、toString方法,使用时需配置Lombok,如不配置请手动生成相关方法。
我们返回的信息至少包括code、msg、data三部分,其中code是我们后端和前端约定好的状态码,msg为提示信息,data为返回的具体数据,没有返回数据则为null。除了这三部分外,你还可以定义一些其他字段,比如请求时间timestamp。
定义了统一返回类后,controller层返回数据时统一使用R.success()
方法封装。
@RestController
@RequestMapping("/test")
public class TestController {
@PostMapping("/test1")
public R<List<Student>> getStudent() {
ArrayList<Student> list = new ArrayList<>();
Student student1 = new Student();
student1.setId(1);
student1.setName("name1");
Student student2 = new Student();
student2.setId(2);
student2.setName("name2");
list.add(student1);
list.add(student2);
return R.success(list);
}
}
@Data
class Student {
private Integer id;
private String name;
}
例如在以上代码中,我们的需求是查询学生信息,我们调用这个test1接口就返回了以下的结果:
{
"code": 200,
"msg": "ok",
"data": [
{
"id": 1,
"name": "name1"
},
{
"id": 2,
"name": "name2"
}
],
"timestamp": 1692805971309
}
到这里我们已经基本实现了统一返回格式,但是上面这种实现方式也有一个缺点,就是每次返回数据的时候都需要调用R.success()
方法,非常麻烦,我们希望能够在controller层里直接返回我们实际的数据,即data字段中的内容,然后自动帮我们封装到R.success()
之中,因此我们需要一种更高级的方法。
3.统一返回格式的高级实现
我们需要利用springboot的ResponseBodyAdvice
类来实现这个功能,ResponseBodyAdvice的作用:拦截Controller方法的返回值,统一处理返回值/响应体
/**
* 拦截controller返回值,封装后统一返回格式
*/
@RestControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice<Object> {
@Autowired
private ObjectMapper objectMapper;
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
}
@SneakyThrows
@Override
public Object beforeBodyWrite(Object o, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) {
//如果Controller返回String的话,SpringBoot不会帮我们自动封装而直接返回,因此我们需要手动转换成json。
if (o instanceof String) {
return objectMapper.writeva lueAsString(R.success(o)