SpringBoot自定义全局异常处理器

文章目录

一、介绍

Springboot框架提供两个注解帮助我们十分方便实现全局异常处理器以及自定义异常

  • @ControllerAdvice@RestControllerAdvice(推荐)
  • @ExceptionHandler

二、实现

1. 定义全局异常处理器

定义GlobalExceptionHandler类,拦截所有异常。
@RestControllerAdvice注解使得你可以在GlobalExceptionHandler 中处理异常,@ExceptionHandle注解用于将指定异常绑定到处理的函数上。如下使用@ExceptionHandler(Exception.class)即对所有异常进行捕获处理。

java 复制代码
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public RestErrorResponse exception(Exception e){
        //record log
        log.error("系统异常{}", e.getMessage(),e);
        //decode errorException
        String errMessage = "系统异常";
        return new RestErrorResponse(errMessage);
    }
}
java 复制代码
@Data
@AllArgsConstructor
public class RestErrorResponse implements Serializable {
    private String errMessage;
}

事实上,写到这里已经可以用了,RestErrorResponse 用来承载错误信息到前端,因为@RestControllerAdvice已经包含了@ResponseBody

2. 自定义异常类

继承RuntimeException 异常类写一个自定义的异常类。这么做主要是能够使用自定义的枚举类来更优雅的抛出错误。

java 复制代码
@Data
public class XueChengPlusException extends RuntimeException {

    private String errMessage;

    public XueChengPlusException() {
        super();
    }

    public XueChengPlusException(String errMessage) {
        super(errMessage);
        this.errMessage = errMessage;
    }

    public static void cast(CommonError commonError){
        throw new XueChengPlusException(commonError.getErrMessage());
    }
    public static void cast(String errMessage){
        throw new XueChengPlusException(errMessage);
    }

}
java 复制代码
@Getter
public enum CommonError {
    UNKOWN_ERROR("执行过程异常,请重试。"),
    PARAMS_ERROR("非法参数"),
    OBJECT_NULL("对象为空"),
    QUERY_NULL("查询结果为空"),
    REQUEST_NULL("请求参数为空");

    private String errMessage;

    private CommonError( String errMessage) {
        this.errMessage = errMessage;
    }
}

同时,对于GlobalExceptionHandler 也要做一些修改,一方面处理自定义异常,另一方处理其余异常。

java 复制代码
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {

    @ExceptionHandler(XueChengPlusException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public RestErrorResponse customException(XueChengPlusException e){
        //record log
        log.error("系统异常{}", e.getErrMessage(),e);
        //decode errorException
        String errMessage = e.getErrMessage();
        return new RestErrorResponse(errMessage);
    }

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public RestErrorResponse exception(Exception e){
        //record log
        log.error("系统异常{}", e.getMessage(),e);
        //decode errorException
        String errMessage = CommonError.UNKOWN_ERROR.getErrMessage();
        return new RestErrorResponse(errMessage);
    }
}

三、使用

在程序中任意地方抛出异常,controllerservicedao层都可以,比如

java 复制代码
throw new RuntimeException("价格不能为空且必须大于0");

这时走的就是

java 复制代码
	@ExceptionHandler(Exception.class)
    public RestErrorResponse exception(Exception e)

除此之外,可以这样抛出自定义异常,比如

java 复制代码
XueChengPlusException.cast(CommonError.PARAMS_ERROR);
java 复制代码
XueChengPlusException.cast("其他的消息");
java 复制代码
throw new XueChengPlusException(CommonError.OBJECT_NULL.getErrMessage());
java 复制代码
throw new XueChengPlusException("其他的消息");

这时走的就是

java 复制代码
	@ExceptionHandler(XueChengPlusException.class)
    public RestErrorResponse customException(XueChengPlusException e)

四、疑问

Q:疑问,XueChengPlusException异常类继承自RuntimeException ,而RuntimeException 继承自Exception,为什么触发customException而不是exception?

在这个全局异常处理器中,当抛出一个XueChengPlusException异常时,它会被customException(XueChengPlusException e)方法处理,而不是exception(Exception e)方法。

这是因为Spring框架的异常处理机制会优先匹配最具体的异常类型。在您的代码中,XueChengPlusExceptionRuntimeException(以及Exception)的子类,因此它更具体。所以,当抛出一个XueChengPlusException异常时,Spring会优先调用处理XueChengPlusException的方法,而不是处理Exception的方法。

这种行为确实表明全局异常处理器有一定的优先级和覆盖逻辑。具体来说,处理器会优先处理更具体的异常类型,如果没有找到匹配的处理器,那么它会寻找处理更一般异常类型的处理器。

相关推荐
ihuyigui9 小时前
海外签收通知短信接口
android·java·开发语言·前端·数据库·后端
海棠Flower未眠9 小时前
SpringBoot 消息死信队列(荣耀典藏版)
java·数据库·spring boot
腾渊信息科技公司9 小时前
Spring Boot + TDengine:工业视觉检测数据实时同步方案实战
spring boot·后端·tdengine
暖和_白开水9 小时前
数据分析agent (七):contextvars 模块上下文request_id
java·前端·数据分析
用户40966601317519 小时前
MyBatis、MyBatis-Plus、通用 Mapper:一张图说清三者的血缘关系
后端
爬楼的猪9 小时前
WSL 的 GUI 为什么总是卡卡的
后端
weixin_7275356210 小时前
MinIO大文件上传深度拆解:从原理到生产落地的完整指南
java·中间件
摇滚侠10 小时前
Java 全栈开发实战教程 课程笔记 34-36
java·笔记
芝士熊爱编程11 小时前
创建型模式-单例模式
java·单例模式·设计模式
程序猿DD11 小时前
OPC必备!在 Cloudflare Worker 上免费部署 AI 网关:集中管理与供应 Token
后端