Controller Advice

通常,@ExceptionHandler@InitBinder@ModelAttribute 方法在其声明所在的 @Controller 类(或类层级)内生效。如果您希望这些方法更全局地生效(跨越多个 controller),可以在使用 @ControllerAdvice@RestControllerAdvice 注解的类中声明它们。

@ControllerAdvice 使用 @Component 进行注解,这意味着此类可以通过组件扫描注册为 Spring Bean。@RestControllerAdvice 是一个组合注解,它同时使用了 @ControllerAdvice@ResponseBody 注解,这本质上意味着 @ExceptionHandler 方法会通过消息转换(而非视图解析或模板渲染)渲染到响应体中。

在启动时,用于 @RequestMapping@ExceptionHandler 方法的基础设施类会检测使用 @ControllerAdvice 注解的 Spring Bean,然后在运行时应用它们的方法。全局 @ExceptionHandler 方法(来自 @ControllerAdvice)在局部方法(来自 @Controller之后 应用。相比之下,全局 @ModelAttribute@InitBinder 方法在局部方法 之前 应用。

默认情况下,@ControllerAdvice 方法应用于每个请求(即所有 controller),但您可以通过使用注解上的属性将其范围缩小到 controller 的子集,如下例所示

  • Java

  • Kotlin

// Target all Controllers annotated with @RestController
@ControllerAdvice(annotations = RestController.class)
public class ExampleAdvice1 {}

// Target all Controllers within specific packages
@ControllerAdvice("org.example.controllers")
public class ExampleAdvice2 {}

// Target all Controllers assignable to specific classes
@ControllerAdvice(assignableTypes = {ControllerInterface.class, AbstractController.class})
public class ExampleAdvice3 {}
// Target all Controllers annotated with @RestController
@ControllerAdvice(annotations = [RestController::class])
public class ExampleAdvice1 {}

// Target all Controllers within specific packages
@ControllerAdvice("org.example.controllers")
public class ExampleAdvice2 {}

// Target all Controllers assignable to specific classes
@ControllerAdvice(assignableTypes = [ControllerInterface::class, AbstractController::class])
public class ExampleAdvice3 {}

前面示例中的选择器在运行时进行评估,如果广泛使用,可能会对性能产生负面影响。有关更多详细信息,请参阅 @ControllerAdvice 的 javadoc。