SpringBoot自定义全局异常处理器的问题总结
作者:木子dn
一、介绍
Springboot
框架提供两个注解帮助我们十分方便实现全局异常处理器
以及自定义异常
。
@ControllerAdvice
或@RestControllerAdvice
(推荐)@ExceptionHandler
二、实现
1. 定义全局异常处理器
定义GlobalExceptionHandler
类,拦截所有异常。@RestControllerAdvice
注解使得你可以在GlobalExceptionHandler
中处理异常,@ExceptionHandle
注解用于将指定异常绑定到处理的函数上。如下使用@ExceptionHandler(Exception.class)
即对所有异常进行捕获处理。
@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); } }
@Data @AllArgsConstructor public class RestErrorResponse implements Serializable { private String errMessage; }
事实上,写到这里已经可以用了,RestErrorResponse
用来承载错误信息到前端,因为@RestControllerAdvice
已经包含了@ResponseBody
。
2. 自定义异常类
继承RuntimeException
异常类写一个自定义的异常类。这么做主要是能够使用自定义的枚举类来更优雅的抛出错误。
@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); } }
@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
也要做一些修改,一方面处理自定义异常,另一方处理其余异常。
@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); } }
三、使用
在程序中任意地方抛出异常,controller
、service
、dao
层都可以,比如
throw new RuntimeException("价格不能为空且必须大于0");
这时走的就是
@ExceptionHandler(Exception.class) public RestErrorResponse exception(Exception e)
除此之外,可以这样抛出自定义异常,比如
XueChengPlusException.cast(CommonError.PARAMS_ERROR);
XueChengPlusException.cast("其他的消息");
throw new XueChengPlusException(CommonError.OBJECT_NULL.getErrMessage());
throw new XueChengPlusException("其他的消息");
这时走的就是
@ExceptionHandler(XueChengPlusException.class) public RestErrorResponse customException(XueChengPlusException e)
四、疑问
Q:疑问,XueChengPlusException异常类继承自RuntimeException ,而RuntimeException 继承自Exception,为什么触发customException而不是exception?
在这个全局异常处理器中,当抛出一个XueChengPlusException
异常时,它会被customException(XueChengPlusException e)
方法处理,而不是exception(Exception e)
方法。
这是因为Spring框架的异常处理机制会优先匹配最具体的异常类型。在您的代码中,XueChengPlusException
是RuntimeException
(以及Exception
)的子类,因此它更具体。所以,当抛出一个XueChengPlusException
异常时,Spring会优先调用处理XueChengPlusException
的方法,而不是处理Exception
的方法。
这种行为确实表明全局异常处理器有一定的优先级和覆盖逻辑。具体来说,处理器会优先处理更具体的异常类型,如果没有找到匹配的处理器,那么它会寻找处理更一般异常类型的处理器。
到此这篇关于SpringBoot自定义全局异常处理器的文章就介绍到这了,更多相关SpringBoot全局异常处理器内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!