控制器切面 (@ControllerAdvice)
@ControllerAdvice 是一个“增强型”控制器,允许你将 @ExceptionHandler、@InitBinder 和 @ModelAttribute 方法应用到所有的控制器上,从而实现全局的逻辑复用。
基本用法
java
@ControllerAdvice
public class GlobalHandler {
@ExceptionHandler(Exception.class)
public String handleAll(Exception ex) {
return "error"; // 全局未捕获异常统一跳转到 error 页面
}
@ModelAttribute
public void addAttributes(Model model) {
model.addAttribute("siteName", "我的Spring文档库"); // 所有页面都能访问到 siteName
}
}kotlin
@ControllerAdvice
class GlobalHandler {
@ExceptionHandler(Exception::class)
fun handleAll(ex: Exception): String {
return "error"
}
@ModelAttribute
fun addAttributes(model: Model) {
model.addAttribute("siteName", "我的Spring文档库")
}
}核心特性
- @RestControllerAdvice:整合了
@ControllerAdvice和@ResponseBody,非常适合作为全局 REST 异常处理器。 - 扫描机制:它是
@Component的特化,会被 Spring 自动扫描并注册。 - 应用优先级:局部处理方法(在 Controller 内部定义的)优先级高于全局处理方法。
- 精准打击:可以通过属性限制其生效范围(如只针对特定包,或只针对标注了某个注解的控制器)。
补充教学
1. 它是 AOP 在 Web 层的体现
虽然名字叫 Advice,但它并不使用标准的长链式代理。Spring 在启动时会检测所有这样的 Bean,并将它们的逻辑整合进请求处理流程中。
2. 避免全局污染
如果你定义了一个针对所有包的注解,可能连第三方库的控制器都被你影响了。推荐总是指定扫描包:
java
@ControllerAdvice("com.mycompany.webapp.controllers")3. 多切面排序
如果你有多个 @ControllerAdvice 类,它们的执行顺序非常重要(尤其是异常匹配时)。 对策:使用 @Order 注解或实现 Ordered 接口。序号越小,优先级越高。通常你应该让处理通用异常的 Advice 优先级降低,让处理业务异常的优先级升高。