控制器建议
通常,@ExceptionHandler、@InitBinder 和 @ModelAttribute 方法是在它们被声明的 @Controller 类(或类层次结构)中应用的。如果你希望这些方法具有更全局的作用范围(适用于所有控制器),你可以将它们声明在一个标注了 @ControllerAdvice 或 @RestControllerAdvice 的类中。
@ControllerAdvice 被 @Component 注解所标记,这意味着这样的类可以通过 组件扫描 被注册为 Spring 容器中的bean。@RestControllerAdvice 是一个组合注解,它同时拥有 @ControllerAdvice 和 @ResponseBody 的注解,其本质含义是:@ExceptionHandler 方法的处理结果会通过消息转换直接写入响应体中(而不是通过视图解析或模板渲染来展示)。
在启动时,@RequestMapping和@ExceptionHandler方法的基础设施类会检测带有@ControllerAdvice注解的Spring Bean,然后在运行时应用这些方法。全局@ExceptionHandler方法(来自@ControllerAdvice)会在局部@ExceptionHandler方法之后被应用。相比之下,全局@ModelAttribute和@InitBinder方法则会在局部方法之前被应用。
默认情况下,@ControllerAdvice方法会应用于每一个请求(即所有控制器),但你可以通过在该注解上使用属性来将其应用范围限定在部分控制器上,如下例所示:
- 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。