题记
生活不可能像你想象得那么好,但也不会像你想象得那么糟。
改变不了环境,就改变自己的心态。
起因
最近,闲来无事,就东瞅瞅西看看,也没发现什么。无意中翻了翻项目,看到项目中使用注解 @RestControllerAdvice,是用来做全局异常处理的,好多项目都使用这个了。最在我想关闭项目的时候,在一个角落中发现有一个项目中使用了@ControllerAdvice。话说@RestControllerAdvice是@ControllerAdvice升级版,心想着还是有区别的,特此来整理分析下,希望大家多多指教!
进入正题
在我们使用的Spring 框架中,@ControllerAdvice 和 @RestControllerAdvice 是处理控制器层横切逻辑的核心注解,二者均基于 AOP 思想,用于集中管理全局异常处理、数据绑定等通用功能,但适用场景有所不同。
一、@ControllerAdvice:面向 MVC 视图的全局处理
@ControllerAdvice 是一个增强型注解,主要作用于传统 MVC 控制器(返回视图的控制器),用于抽取控制器中重复的逻辑,实现全局异常处理、全局数据绑定和请求预处理。
-
全局异常处理
配合@ExceptionHandler注解,统一捕获所有控制器抛出的异常,返回错误视图或跳转页面。@ControllerAdvice public class MvcGlobalExceptionHandler { // 处理空指针异常,返回错误页面 @ExceptionHandler(NullPointerException.class) public ModelAndView handleNullPointerException(NullPointerException e) { ModelAndView mv = new ModelAndView(); mv.addObject("errorMsg", "空指针异常:" + e.getMessage()); mv.setViewName("error"); // 跳转到 error.html 视图 return mv; } } -
全局数据绑定
通过@ModelAttribute定义全局数据,所有控制器和视图可直接访问(如系统配置信息)。@ControllerAdvice public class MvcGlobalData { @ModelAttribute("sysInfo") public Map<String, String> getSiteInfo() { Map<String, String> info = new HashMap<>(); info.put("name", "xxx系统"); info.put("version", "v1.0.1"); return info; // 视图中可通过 ${sysInfo.name} 访问 } } -
范围控制 可通过属性限制作用范围,例如仅对特定包生效:
@ControllerAdvice(basePackages = "com.example.mvc.controller") public class CustomMvcAdvice { ... }
二、@RestControllerAdvice:面向 REST API 的全局处理
@RestControllerAdvice 是 @ControllerAdvice 与 @ResponseBody 的组合注解,专门用于 RESTful 接口(返回 JSON/XML 等数据的控制器),其核心功能与 @ControllerAdvice 一致,但默认将处理结果转换为响应体(无需手动添加 @ResponseBody)。
-
全局异常处理
统一捕获 REST 接口异常,返回 JSON 格式的错误信息。@RestControllerAdvice public class RestGlobalExceptionHandler { // 处理自定义业务异常 @ExceptionHandler(BusinessException.class) public ResponseEntity<ErrorResult> handleBusinessException(BusinessException e) { ErrorResult error = new ErrorResult(e.getCode(), e.getMessage()); return ResponseEntity.status(400).body(error); } // 处理参数校验异常 @ExceptionHandler(MethodArgumentNotValidException.class) public ErrorResult handleValidationException(MethodArgumentNotValidException e) { String msg = e.getBindingResult().getFieldError().getDefaultMessage(); return new ErrorResult("400", msg); // 自动转为 JSON } } // 错误响应实体 @Data class ErrorResult { private String code; private String message; // 构造方法省略 } -
全局数据绑定
为所有 REST 接口注入通用数据(如请求 ID、时间戳)。@RestControllerAdvice public class RestGlobalData { @ModelAttribute("requestId") public String getRequestId() { return UUID.randomUUID().toString(); // 所有接口响应可包含此数据 } } -
范围控制
同样支持限制作用范围,例如仅对 API 控制器生效:@RestControllerAdvice(basePackageClasses = ApiController.class) public class ApiAdvice { ... }
三、二者的核心区别
| 特性 | @ControllerAdvice | @RestControllerAdvice |
|---|---|---|
| 本质 | 增强控制器的通用逻辑 | @ControllerAdvice + @ResponseBody |
| 返回值处理 | 需手动配置视图解析(返回页面) | 自动将返回值转为 JSON/XML 响应体 |
| 适用场景 | 传统 MVC 视图渲染(如 JSP/Thymeleaf) | RESTful API 接口(前后端分离) |
| 异常处理返回形式 | 通常返回错误页面 | 通常返回 JSON 错误信息 |
四、逻辑图
-
客户端请求进入:
DispatcherServlet接收请求 -
模型预处理:执行所有
@ModelAttribute方法 -
控制器执行:调用匹配的控制器方法
-
异常检测:
- 出现异常 → 查找匹配的
@ExceptionHandler - 无异常 → 返回正常结果
- 出现异常 → 查找匹配的
-
结果处理:
@ControllerAdvice:视图渲染@RestControllerAdvice:JSON序列化
总结
-
@ControllerAdvice主要适用于传统 MVC 项目,专注于视图层的全局处理,需通过视图解析器返回页面。如果需要返回json格式的数据,需要和注解@ResponseBody进行搭配使用。 -
@RestControllerAdvice适用于前后端分离的 RESTful 项目,自动将处理结果转为响应体,比如说json或者xml格式的数据,从而达到简化效果。 -
二者均体现了 “集中管理横切逻辑” 的设计思想,减少代码冗余,提升项目可维护性。主要还是一点,根据需求来选择合适的注解,主要是自己喜欢就好,哈哈!
展望
祝愿看到这篇文章的掘友:
工作顺心,收入翻倍,灵感不断,好运连连!
愿前程似锦,未来可期,不负韶华,不负自己。