在上一篇文章中介绍了 《Springboot设计通用返回类》
本篇文章介绍设计通用错误处理。
通常在项目中需要设计统一的错误消息。
使用枚举类来定义“错误码”与“错误消息”是一个非常好的选择,并且可以实现错误消息自定义。
1. 定义通用错误接口类
该接口定义 获取错误码、获取错误信息、设置错误信息
// 定义通用错误接口类
public interface CommonError {
// 获取错误码
int getErrorCode();
// 获取错误信息
String getErrorMessage();
// 设置错误信息,用于覆盖默认错误信息
CommonError setErrorMessage(String errorMessage);
}
2. 定义通过错误枚举类
定义错误枚举类,实现至CommonError接口
/**
* 定义错误枚举类,实现至CommonError接口
**/
public enum EnumError implements CommonError {
// 定义几个常用示例
UNKNOWN_ERROR(1001, "未知错误"),
METHOD_ERROR(1002, "方法不可用"),
PARAMETER_ERROR(1003, "参数不合法");
private int errorCode;
private String errorMessage;
EnumError(int errorCode, String errorMessage){
this.errorCode = errorCode;
this.errorMessage = errorMessage;
}
@Override
public int getErrorCode() {
return errorCode;
}
@Override
public String getErrorMessage() {
return errorMessage;
}
@Override
public CommonError setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
return this;
}
}
3. 定义通过报错类
// 定义通用抛错类
public class BusinessException extends Exception implements CommonError{
// 定义CommonError属性
private CommonError commonError;
// 通用构造器
public BusinessException(CommonError commonError){
super();
this.commonError = commonError;
}
// 重写ErrorMessage构造器
public BusinessException(CommonError commonError, String errorMessage){
super();
this.commonError = commonError;
this.commonError.setErrorMessage(errorMessage);
}
@Override
public int getErrorCode() {
return this.commonError.getErrorCode();
}
@Override
public String getErrorMessage() {
return this.commonError.getErrorMessage();
}
// 重写errorMessage
@Override
public CommonError setErrorMessage(String errorMessage) {
return this.commonError.setErrorMessage(errorMessage);
}
}
4. 定义全局异常捕获处理类
@ControllerAdvice可以实现全局异常处理
@ControllerAdvice
public class ControllerExceptionHandler {
// 定义ExceptionHandler解决未被Controller捕获的通用Exception错误
@ExceptionHandler(value = Exception.class)
@ResponseBody
public CommonResponseData exceptionHandler(Exception exception){
Map<String, Object> responseData = new HashMap<>();
responseData.put("errorMessage", EnumError.UNKNOWN_ERROR.getErrorMessage());
int errorCode = EnumError.UNKNOWN_ERROR.getErrorCode();
return CommonResponseData.create(errorCode, responseData);
}
// 定义BusinessExceptionHandler解决未被Controller捕获的BusinessExceptionHandler
@ExceptionHandler(value = BusinessException.class)
@ResponseBody
public CommonResponseData BusinessExceptionHandler(BusinessException businessException){
Map<String, Object> responseData = new HashMap<>();
responseData.put("errorMessage", businessException.getErrorMessage());
int errorCode = businessException.getErrorCode();
return CommonResponseData.create(errorCode, responseData);
}
}
5. 在Controller中主动抛错
主动抛错BusinessException,并重写错误信息
@RequestMapping(value = "/")
@RestController
public class UserController {
@PostMapping(value = "/login")
public CommonResponseData login(@RequestParam(name = "username") String username,
@RequestParam(name = "password") String password) throws BusinessException {
// 参数不为空校验
if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)){
// 主动抛错
throw new BusinessException(EnumError.PARAMETER_ERROR, "username or password is empty");
}
// 验收用户名和密码是否正常
// ....
return CommonResponseData.create("login success");
}
}
6. 测试效果
通过Postman测试login接口,返回预期结果