淘先锋技术网

首页 1 2 3 4 5 6 7

统一异常处理

目标:想让异常结果也显示为统一的返回结果对象,并且统一处理系统的异常信息,那么需要进行统一异常处理。

结构图

在这里插入图片描述

  • 自定义异常类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("保存失败");
    }
}

5、测试

在这里插入图片描述