前言
看了廖师兄的视频后,结合自己以前的编程经验总结下 :
在 web 开发过程中, 后端要统一返回的数据结构,便于前端处理。例如每个请求,我们都需要知道 :
- code : 服务器返回的状态码(主要给程序员看)。例如 : 200 : 请求成功。 500 : 服务器内部错误。
- status : 0 或者 1 (用于给前端判断) 。 1 : 处理成功。 0 : 处理失败 。这里要和 code 做区分。status 是逻辑上的错误。例如用户想要删除某一个帖子,用户手滑,连续发了两个请求, 第一个请求成功, 服务器返回 code: 200 , status : 1 。第二个请求成功,但是帖子已经被删除了。因此返回 code : 200 , status : 0 ,msg: “帖子不存在”
- msg : 服务器的错误信息 ,主要返回给用户看。
- data : 服务器返回的数据。
返回的数据格式如下 :
这样封装的对前端有很多好处,前端可以直接判断,比如 :
if(status == 1(
...//直接拿 data 里面的数据处理。
)else {
// 直接对话框或者 Toast 显示 msg 给用户,客户端不需要再做逻辑判断。
}
code: 用于前后端撕逼。
例如用户登录服务器返回以下数据 :
客户端只需要判断, status 为 0 , 然后直接给用户显示 msg 即可。
code : 103 为 前端和后端约定好的错误码。 例如 : 103 表示用户账号已被封号。
代码片段
例如接口定义如下 :
@GetMapping(path = "/user/findAll")
public BaseResult<List<User>> findAllUsers() {
List<User> users = userDao.findAll();
return ResultUtil.success(users);
}
BaseResult :
public class BaseResult<T> {
private Integer code;
private Integer status;
private String msg;
private T data;
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
ResultUtil :
public class ResultUtil {
public static <T> BaseResult<T> success(T data) {
return commonResult(1, 200, "请求成功", data);
}
public static <T> BaseResult<T> error(String errorMsg) {
return error(200, errorMsg);
}
public static <T> BaseResult<T> error(Integer code, String errorMsg) {
return commonResult(0, code, errorMsg, null);
}
private static <T> BaseResult<T> commonResult(Integer status, Integer code, String errMsg, T data) {
BaseResult<T> result = new BaseResult<>();
result.setStatus(status);
result.setCode(code);
result.setMsg(errMsg);
result.setData(data);
return result;
}
}
统一的异常处理
Spring Boot 在有异常发生时,默认返回的 Json 数据结构如下 : (用 Postman 测试接口)
{
"timestamp": "2018-10-20T02:39:20.506+0000",
"status": 500,
"error": "Internal Server Error",
"message": "No message available",
"path": "/user/findAll"
}
很明显上面 Json 返回的字段不是我们想要的类型,我们可以处理下。
新建一个 BaseException : 这个异常为服务端主动抛出 , 例如用户没有登录,输入密码错误, 服务器直接抛出该异常,然后交由全局异常处理。
public class BaseException extends RuntimeException {
// 错误信息
private String errorMsg;
// 服务器状态码
private Integer code;
public BaseException(String errorMsg) {
super(errorMsg);
this.errorMsg = errorMsg;
}
public BaseException(Integer code, String errorMsg) {
super(errorMsg);
this.errorMsg = errorMsg;
this.code = code;
}
public String getErrorMsg() {
return errorMsg;
}
public Integer getCode() {
return code;
}
}
全局捕获异常 :
@ControllerAdvice
public class GlobalExceptionHandle {
@ExceptionHandler(value = Exception.class)
@ResponseBody
public <T> BaseResult<T> handle(Exception e) {
if (e instanceof BaseException) {
Integer code = 104;
BaseException exception = (BaseException) e;
if (exception.getCode() != 0) {
code = exception.getCode();
}
return ResultUtil.error(code, e.getMessage());
}
return ResultUtil.error(500, e.getMessage() == null ? "服务器内部错误" : e.getMessage());
}
}
这里的 104 为 前端和后端约定好的返回码 。