【SpringBoot】_统一功能处理:统一数据返回格式
目录
1. 对所有返回类型方法进行统一数据返回类型处理
2. 部分返回类型方法存在的问题
3. 对两种有误的方法进行处理
仍以图书管理系统为例。
创建Result对后端返回给前端的数据进行封装,增加业务状态码与错误信息,将原本的数据作为data部分:
package com.example.bookmanagementsystem.model;
import com.example.bookmanagementsystem.enums.ResultCode;
import lombok.Data;
@Data
public class Result<T> {
// 业务状态码:0-成功, -1-失败, -2未登录;
private ResultCode code;
// 错误信息;
private String errMsg;
// 数据
private Object data;
public static <T> Result<T> success(T data){
Result result=new Result();
result.setCode(ResultCode.SUCCESS);
result.setErrMsg("");
result.setData(data);
return result;
}
public static <T> Result<T> fail(String errMsg,Object data){
Result result=new Result();
result.setCode(ResultCode.FAIL);
result.setErrMsg(errMsg);
result.setData(data);
return result;
}
public static <T> Result<T> fail(String errMsg){
Result result=new Result();
result.setCode(ResultCode.FAIL);
result.setErrMsg(errMsg);
result.setData(null);
return result;
}
public static <T> Result<T> unlogin(){
Result result=new Result();
result.setCode(ResultCode.UNLOGIN);
result.setErrMsg("用户未登录");
result.setData(null);
return result;
}
}
将getBookListByPage方法的返回值修改为Result:
@RequestMapping("/getBookListByPage")
public Result getBookListByPage(PageRequest pageRequest, HttpSession session){
log.info("接收到查询翻页信息:pageRequest:{}",pageRequest);
// 校验成功
if(pageRequest.getPageSize()<0 || pageRequest.getCurrentPage()<1) {
return Result.fail("参数校验失败");
}
PageResult<BookInfo> bookInfoPageResult=null;
try{
bookInfoPageResult = bookService.selectBookInfoByPage(pageRequest);
return Result.success(bookInfoPageResult);
}catch (Exception e){
log.error("查询翻页信息错误:e{}",e);
return Result.fail(e.getMessage());
}
}
为了实现后端方法返回给前端的数据都被封装为Result类型,若逐个修改封装会非常麻烦,接下来采用统一数据返回对现有方法进行处理。
1. 对所有返回类型方法进行统一数据返回类型处理
在config包下创建一个ResponseAdvice类,表示控制器通知类:
package com.example.bookmanagementsystem.config;
import com.example.bookmanagementsystem.model.Result;
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;
@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) {
// 返回前需要执行的操作:封装
return Result.success(body);
}
}
1、控制器通知类需要使用@ControllerAdvice注解,并实现ResponseBodyAdvice接口;
2、控制器通知类需要重写supports方法和beforeBodyWrite方法:
(1)supports方法:返回值为布尔类型,表示是否执行beforeBodyWrite方法:
若返回值为true表示执行,false表示不执行;
(2)beforeBodyWrite方法:对response方法进行具体操作;
2. 部分返回类型方法存在的问题
1、当返回类型为Result时:(Result类型已进行返回类型的封装)
登录后,测试getBookListByPage方法:
body就是返回的结果,但success方法已经进行了封装,故而导致两遍封装:
2、当返回类型为String时:
登录后,对updateBook方法进行测试:
可见HTTP状态码为500,表示服务器内部执行有误。但此时采用的统一数据返回形式却将业务状态码置为SUCCESS,出现错误;
综上:
当前统一数据返回格式处理对于两种返回类型的方法存在错误:
(1)返回类型为Result时出现嵌套封装;
(2)返回类型为String时无法正确处理;
3. 对两种有误的方法进行处理
修改ResponseAdvice类:
package com.example.bookmanagementsystem.config;
import com.example.bookmanagementsystem.model.Result;
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;
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
@Autowired
private ObjectMapper objectMapper;
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
}
@SneakyThrows // lombok提供的处理异常的注解:编译后处理为try catch;
@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)对于返回类型为Result的方法进行处理,当body为Result时直接返回body即可,无需进行统一数据返回;
(2)对于返回类型为String类型的方法进行处理,此时需使用jackson的ObjectMapper类,实例化对象后调用writeValueAsString方法进行处理;
使用postman进行测试:
1、使用getBookListByPage方法(返回值为Result类型)进行测试:
2、使用updateBook方法(返回值为String类型)进行测试: