Skip to content

控制器切面 (@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 优先级降低,让处理业务异常的优先级升高。

Based on Spring Framework.