统一接口返回和全局异常处理

1、为什么需要统一返回类?

规范化返回的信息、提高代码的可读性和维护性,同时减少重复劳动。

2、为什么需要全局异常处理?

如果不做全局异常处理,代码中的异常要用一些try-catch、throw来处理,这样做会不仅提高了代码的耦合度还会影响代码的美观。

好处:标准化、简化代码的业务逻辑、友好返回。

统一接口返回

1、基础返回类

  1. 编写需要的字段(一般为code、data、message)
  2. 编写需要的语法糖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* @Description: 基础返回类
* @Author: ler
*/
@Data
public class BaseResponse<T> implements Serializable {
// 错误码
private int code;
// 数据
private T data;
// 信息
private String message;

public BaseResponse(int code, T data, String message) {
this.code = code;
this.data = data;
this.message = message;
}
public BaseResponse(int code, T data) {
this.code = code;
this.data = data;
}
public BaseResponse(ErrorCode errorCode) {
this(errorCode.getCode(), null, errorCode.getMessage());
}
}

2、错误码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
* 错误码
* @author ler
*/
public enum ErrorCode {

SUCCESS(20000, "成功"),
PARAMS_ERROR(40000, "请求参数错误"),
NOT_LOGIN_ERROR(40100, "未登录"),
NO_AUTH_ERROR(40101, "无权限"),
NOT_FOUND_ERROR(40400, "请求数据不存在"),
FORBIDDEN_ERROR(40300, "禁止访问"),
SYSTEM_ERROR(50000, "系统内部异常"),
OPERATION_ERROR(50001, "操作失败");

/**
* 错误码
*/
private final int code;
/**
* 错误信息
*/
private final String message;

ErrorCode(int code, String message) {
this.code = code;
this.message = message;
}

public int getCode() {
return code;
}

public String getMessage() {
return message;
}
}

3、返回工具类

不用 new 了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class ResultUtils {

public static <T> BaseResponse<T> success(T data){
return new BaseResponse<>(0, data, "success");
}

public static BaseResponse error(ErrorCode errorCode){
return new BaseResponse<>(errorCode);
}

public static BaseResponse error(int code, String message, String description){
return new BaseResponse<>(code, message, description);
}

public static BaseResponse error(ErrorCode errorCode, String message){
return new BaseResponse<>(errorCode.getCode(), message);
}

public static BaseResponse error(ErrorCode errorCode, String message, String description){
return new BaseResponse<>(errorCode.getCode(), message, description);
}
}

全局异常处理

1、创建业务异常类

  1. 继承 RuntimeException
  2. 编写需要的字段(一般是 code、description)
  3. 编写一些语法糖,用于处理业务中需要的字段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
* 业务异常
* @author ler
*/
@Data
public class BusinessException extends RuntimeException{
// 错误码
private int code;
// 错误信息
private String description;

// 语法糖
public BusinessException(int code, String description) {
super(description);
this.code = code;
}
public BusinessException(ErrorCode errorCode) {
super(errorCode.getMessage());
this.code = errorCode.getCode();
}
public BusinessException(ErrorCode errorCode, String description) {
super(errorCode.getMessage());
this.code = errorCode.getCode();
this.description = description;
}
}

2、编写全局异常处理类

  1. 在类名上标注 @RestControllerAdvice 注解
  2. 在方法名上标注 @ExceptionHandler(BusinessException.class) 注解
  3. 编写异常处理逻辑
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 全局异常处理
* @author ler
*/
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

@ExceptionHandler(BusinessException.class)
public BaseResponse businessExceptionHandler(BusinessException e) {
log.error("businessException: " + e.getMessage(), e);
return ResultUtils.error(e.getCode(), e.getMessage(), e.getDescription());
}

@ExceptionHandler(RuntimeException.class)
public BaseResponse runtimeExceptionHandler(RuntimeException e) {
log.error("runtimeException: " + e.getMessage(), e);
return ResultUtils.error(ErrorCode.SYSTEM_ERROR, e.getMessage(), "");
}
}