异常处理
全局异常
全局异常处理的本质是把“异常处理”从业务代码中抽离出来,统一交给框架层处理;Spring Boot 的全局异常处理,本质是通过 HandlerExceptionResolver 在 MVC 层拦截异常,并根据 @ExceptionHandler 映射规则,将异常转换为统一的 HTTP 响应。
@RestControllerAdvice
@RestControllerAdvice 注解用于声明一个“全局异常处理组件”,作用范围是所有 Controller;如下:
@RestControllerAdvice // ← 这是让 Spring 识别的关键注解
public class GlobalExceptionHandler {
@ExceptionHandler(BusinessException.class) // ← 指定要处理的异常类型
public Result<Void> handleBusinessException(BusinessException exception) {
// ...
}
}
@RestControllerAdvice 声明的类会被 Spring 扫描进容器,然后参与 MVC 的异常处理流程。
@RestControllerAdvice 和 @ControllerAdvice 的主要区别是返回值;@ControllerAdvice 注解的类,其中的方法返回值默认走视图解析(返回页面),@RestControllerAdvice 注解的类,其中的方法默认返回 JSON(适合前后端分离);
注:@RestControllerAdvice 的“作用范围是 Controller”,指的是它只处理 Controller 层“向外抛出的异常”,而不是“异常必须在 Controller 内产生”;异常可以来自 Service、DAO 层等,如下:
Service 抛异常
↓
Controller 没 try-catch
↓
异常继续向上抛
↓
DispatcherServlet 捕获
↓
HandlerExceptionResolver 开始处理
@ExceptionHandler
在 @RestControllerAdvice 标注的类中定义 @ExceptionHandler 方法并指定异常类型后,当该异常在请求处理过程中抛出并传播至 Controller 层时,会被该方法拦截处理;其返回值由于 @ResponseBody 语义会被写入响应体,并由 HttpMessageConverter(如 Jackson)序列化为 JSON 返回给前端。
@ExceptionHandler(BusinessException.class)
public Result<Void> handleBusinessException(BusinessException exception){
return Result.error(exception.getCode(), exception.getMessage());
}
@RestControllerAdvice 本身包含了 @ControllerAdvice 和 @ResponseBody 的能力,因此返回值有 @ResponseBody 的功能;而 @ResponseBody 的功能就是:方法返回值不再被当成“页面名”,而是作为“数据”直接写入 HTTP 响应体(response body)中。
Spring Boot 全局异常处理机制
当请求进入 Spring MVC 时,由 DispatcherServlet 分发到目标 Controller 方法执行;若处理过程一切正常,则请求正常返回;若执行过程中抛出异常且未被捕获,异常会沿调用栈回到 DispatcherServlet,随后由 HandlerExceptionResolver 责任链对异常进行解析、处理,最终将其转换为对应的 HTTP 响应并返回客户端。如下:
HTTP 请求
↓
DispatcherServlet
↓
Controller 方法
↓(如果抛异常)
HandlerExceptionResolver(异常解析器链)
↓
返回 HTTP 响应
HandlerExceptionResolver是 异常 到 HTTP 响应 的处理总入口,它不是一个具体实现,而是一个 策略接口(SPI),专门负责:当 Controller 抛出异常后,决定“这个异常怎么变成 HTTP 响应”。Spring 默认提供的 3 个 HandlerExceptionResolver 的核心实现:
ExceptionHandlerExceptionResolver:异常 → 找到匹配的 @ExceptionHandler 注解的方法 → 执行 → 返回 JSON;
ResponseStatusExceptionResolver:异常 → 读取注解 → 设置 HTTP 状态码;
DefaultHandlerExceptionResolver:HttpRequestMethodNotSupportedException → 405;
即,HandlerExceptionResolver是 Spring MVC 的异常处理调度器,它通过责任链模式,将异常分发给不同策略(如 @ExceptionHandler),最终转换为 HTTP 响应
流程梳理
@RestControllerAdvice 会在 Spring 启动时被扫描注册为 Bean,并被 ExceptionHandlerExceptionResolver 识别和解析;其中的 @ExceptionHandler 方法会被提前解析为“异常类型 → 处理方法”的映射表,在运行时当异常被 DispatcherServlet 捕获后,通过异常解析器链匹配并调用对应方法,最终生成 HTTP 响应。
@ExceptionHandler 注解的方法必须写在如下两类注解的 Controller 中:
1. Controller(@Controller / @RestController)
2. ControllerAdvice(@ControllerAdvice / @RestControllerAdvice)
如果@ExceptionHandler 注解的方法不在 Controller 或 ControllerAdvice 中(例如普通 Bean),则不会被 Spring MVC 解析和注册。
优先级规则
在 Controller 中定义的 @ExceptionHandler 属于局部异常处理,只对当前 Controller 生效,并且在匹配到的情况下,优先级高于 @ControllerAdvice(全局异常处理);在 ControllerAdvice 中定义的 @ExceptionHandler 方法,是全局异常处理方法。如果局部和全部都定义时 @ExceptionHandler 时:
Controller 内的 @ExceptionHandler ← 优先
ControllerAdvice 中的处理器 ← 兜底
即:局部优先,全局兜底