统一异常处理
目标:想让异常结果也显示为统一的返回结果对象,并且统一处理系统的异常信息,那么需要进行统一异常处理。
结构图
-
自定义异常类BusinessException,必须继承
RuntimeException
,才能够被抛出。RuntimeException
是那些可能在 Java 虚拟机正常运行期间抛出的异常的超类。可能在执行方法期间抛出但未被捕获的 -
UnifiedExceptionHandler
统一异常处理类,发生指定的异常时,调用该方法,向前端返回规范化的异常错误。 -
@RestControllerAdvice
是一个组合注解,本质上是个Component
,用于定义@ExceptionHandler
,@InitBinder
和@ModelAttribute
方法。 -
@@ExceptionHandler(BusinessException.class)
用来统一处理方法抛出的异常,当BusinessException发生异常时调用。
1、创建统一异常处理器
创建统一异常处理器类UnifiedExceptionHandler
@Component : Spring自动管理
@RestControllerAdvice : 在controller层添加通知。如果使用@ControllerAdvice,则方法上需要添加@ResponseBod
@Component //Spring容易自动管理
@RestControllerAdvice //在controller层添加通知。如果使用@ControllerAdvice,则方法上需要添加@ResponseBody
public class UnifiedExceptionHandler {
/**
* 未定义异常
*/
@ExceptionHandler(value = Exception.class) //当controller中抛出Exception,则捕获
public R handleException(Exception e) {
log.error(e.getMessage(), e);
return R.error();
}
/**
* 自定义异常
*/
@ExceptionHandler(BusinessException.class)
public R handleBusinessException(BusinessException e){
log.error(e.getMessage(), e);
return R.error().message(e.getMessage()).code(e.getCode());
}
}
目标:使用一个或较少的异常类,可以捕获和显示所有的异常信息。
方案:因此,我们可以创建一个自定义异常类(必须是运行时异常),在程序中抛出这个自定义异常对象,并在统一异常处理器中捕获自定义异常对象
2、创建自定义异常类
//自定义异常类
@Data
@NoArgsConstructor
public class BusinessException extends RuntimeException {
//状态码
private Integer code;
//错误消息
private String message;
/**
*
* @param message 错误消息
*/
public BusinessException(String message) {
this.message = message;
}
/**
*
* @param message 错误消息
* @param code 错误码
*/
public BusinessException(String message, Integer code) {
this.message = message;
this.code = code;
}
/**
*
* @param message 错误消息
* @param code 错误码
* @param cause 原始异常对象
*/
public BusinessException(String message, Integer code, Throwable cause) {
super(cause);
this.message = message;
this.code = code;
}
/**
*
* @param resultCodeEnum 接收枚举类型
*/
public BusinessException(ResponseEnum resultCodeEnum) {
this.message = resultCodeEnum.getMessage();
this.code = resultCodeEnum.getCode();
}
/**
*
* @param resultCodeEnum 接收枚举类型
* @param cause 原始异常对象
*/
public BusinessException(ResponseEnum resultCodeEnum, Throwable cause) {
super(cause);
this.message = resultCodeEnum.getMessage();
this.code = resultCodeEnum.getCode();
}
}
3、创建枚举类
@Getter
@AllArgsConstructor
@ToString
public enum ResponseEnum {
SUCCESS(0,"成功"),
ERROR(-1,"服务器内部错误"),
//-1xx 服务器错误
BAD_SQL_GRAMMAR_ERROR(-101, "sql语法错误"),
SERVLET_ERROR(-102, "servlet请求异常"), //-2xx 参数校验
UPLOAD_ERROR(-103, "文件上传错误"),
EXPORT_DATA_ERROR(104, "数据导出失败"),
//-2xx 参数校验
BORROW_AMOUNT_NULL_ERROR(-201, "借款额度不能为空"),
;
// 响应状态码
private Integer code;
// 响应信息
private String message;
}
4、创建Controller
@PostMapping("/save")
public R save(
@RequestBody IntegralGrade integralGrade){
//如果借款额度为空就手动抛出一个自定义的异常!
if(integralGrade.getBorrowAmount() == null){
//BORROW_AMOUNT_NULL_ERROR(-201, "借款额度不能为空"),
throw new BusinessException(ResponseEnum.BORROW_AMOUNT_NULL_ERROR);
}
boolean result = integrationService.save(integralGrade);
if (result) {
return R.ok().message("保存成功");
} else {
return R.error().message("保存失败");
}
}