在 Spring 框架中 @ControllerAdvice 直译就是控制器增强注解 ,是 Spring MVC 基于 AOP 实现的全局控制器统一处理方案,也是日常开发的高频注解。
一、基础概述
1. 基本信息
- 所属包 :
org.springframework.web.bind.annotation.ControllerAdvice - 版本要求:Spring MVC 3.2+ 开始支持
- 核心作用 :对项目中所有标注
@Controller/@RestController的控制器做全局统一增强,抽离通用逻辑,避免重复代码。 - 本质:全局切面,拦截所有控制器的请求流程。
2. 衍生注解(重点区分)
java
// 组合注解 = @ControllerAdvice + @ResponseBody
@RestControllerAdvice
- @ControllerAdvice :默认用于页面跳转 / 视图渲染 ,返回页面;若要返回 JSON,方法需额外加
@ResponseBody。 - @RestControllerAdvice :前后端分离项目首选,天然返回 JSON 格式,接口开发几乎都用它。
二、三大核心功能(搭配不同注解使用)
@ControllerAdvice 本身不单独工作,需要配合以下三个注解实现能力,也是实际开发最常用的三大场景。
场景 1:全局异常处理(⭐ 最常用)
搭配 @ExceptionHandler ,统一捕获所有控制器抛出的异常,统一响应格式、统一异常提示 ,替代每个接口写 try-catch。
1. 第一步:定义统一返回实体
项目标准接口返回格式:
java
import lombok.Data;
@Data
public class Result<T> {
// 响应码:200成功,500系统异常,自定义码区分业务异常
private Integer code;
// 响应信息
private String msg;
// 响应数据
private T data;
// 成功响应
public static <T> Result<T> success(T data) {
Result<T> result = new Result<>();
result.setCode(200);
result.setMsg("请求成功");
result.setData(data);
return result;
}
// 失败响应
public static <T> Result<T> fail(Integer code, String msg) {
Result<T> result = new Result<>();
result.setCode(code);
result.setMsg(msg);
return result;
}
}
2. 第二步:全局异常处理器(核心代码)
java
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
// 全局控制器增强 + 统一返回JSON
@RestControllerAdvice
public class GlobalExceptionHandler {
// 1. 捕获【空指针异常】(精准异常,优先级更高)
@ExceptionHandler(NullPointerException.class)
public Result<Void> handleNullPoint() {
return Result.fail(500, "数据为空,操作失败");
}
// 2. 捕获【所有运行时异常】
@ExceptionHandler(RuntimeException.class)
public Result<Void> handleRuntimeException(RuntimeException e) {
// 可打印日志:log.error("运行时异常:", e);
return Result.fail(500, "业务异常:" + e.getMessage());
}
// 3. 兜底:捕获【所有Exception异常】(父类异常,最后匹配)
@ExceptionHandler(Exception.class)
public Result<Void> handleException(Exception e) {
return Result.fail(500, "系统繁忙,请稍后重试");
}
}
规则说明
- 异常优先级 :具体子类异常 > 父类异常(如上示例:空指针会优先被第一个方法捕获)。
- 局部优先 :如果某个
Controller内部单独写了@ExceptionHandler,会优先使用局部异常处理,全局失效。 - 仅捕获控制器层抛出的异常:Service/DAO 层异常需要向上抛到 Controller 才能被拦截。
场景 2:全局请求参数预处理
搭配 @InitBinder ,全局统一处理表单 / URL 拼接参数,例如:字符串去首尾空格、全局日期格式转换、参数权限过滤等。
注意:该注解对 JSON 请求体(@RequestBody)不生效,JSON 参数转换需使用全局消息转换器。
java
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalParamBinder {
// 全局参数绑定预处理
@InitBinder
public void initBinder(WebDataBinder binder) {
// 示例1:所有字符串参数自动去除首尾空格
binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
// 示例2:禁止绑定指定字段(防止前端篡改敏感字段)
binder.setDisallowedFields("createTime", "updateTime");
}
}
场景 3:全局绑定公共数据
搭配 @ModelAttribute ,在所有接口执行前 ,自动向 Model 中注入公共数据,所有 Controller 都能直接获取。
多用于页面渲染场景,前后端分离接口开发使用较少。
java
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalModelData {
// 所有接口执行前,自动往Model存入数据
@ModelAttribute
public void addCommonData(Model model) {
model.addAttribute("projectName", "测试项目");
model.addAttribute("version", "1.0.0");
}
}
三、限定生效范围(常用属性)
默认 @ControllerAdvice 对全局所有控制器生效,可通过属性限定范围,精准控制作用域:
java
// 1. 指定包路径:只对 com.example.controller 包下的控制器生效
@RestControllerAdvice(basePackages = "com.example.controller")
// 2. 指定类:该类所在包及子包下的控制器生效
@RestControllerAdvice(basePackageClasses = UserController.class)
// 3. 指定注解:只对标记了 @RestController 的类生效
@RestControllerAdvice(annotations = RestController.class)
四、常见踩坑 & 注意事项
-
JSON 参数无法被 @InitBinder 处理
@InitBinder只处理form表单/URL参数,@RequestBody接收的 JSON 参数需要自定义HttpMessageConverter做统一转换。 -
不要捕获
Throwable``Throwable包含 Error(虚拟机级错误:内存溢出、栈溢出),捕获后会掩盖严重系统问题,一般只捕获Exception。 -
过滤器 / 拦截器异常不生效
@ControllerAdvice作用于控制器层 ,Filter、Interceptor抛出的异常不会被拦截。 -
顺序问题全局异常处理器建议单独建类,不要和业务 Controller 写在一起,保证全局统一。
五、总结(开发选型)
| 注解 | 使用场景 |
|---|---|
| @ControllerAdvice | 传统 MVC 项目(返回页面、视图) |
| @RestControllerAdvice | 前后端分离接口项目(主流),统一异常、统一 JSON 返回 |
在企业级项目中,全局异常处理 是 @RestControllerAdvice 最核心的用法,几乎所有 Spring Boot 项目都会标配该组件。