@ExceptionHandler
, @InitBinder
, 和 @ModelAttribute
方法只适用于它们被声明的 @Controller
类,或类的层次结构。如果它们被声明在 @ControllerAdvice
或 @RestControllerAdvice
类中,那么它们就适用于任何控制器。此外,从 5.3 版本开始,@ControllerAdvice
中的 @ExceptionHandler
方法可以用来处理来自任何 @Controller
或任何其他处理器的异常。
@ControllerAdvice
与 @Component
进行了元注解,因此可以通过组件扫描注册为 Spring Bean。@RestControllerAdvice
与@ControllerAdvice
和 @ResponseBody
进行了元注解,这意味着 @ExceptionHandler
方法的返回值将通过响应体信息转换呈现,而不是通过 HTML 视图。
在启动时,RequestMappingHandlerMapping 和 ExceptionHandlerExceptionResolver 会检测控制器 advice bean 并在运行时应用它们。来自@ControllerAdvice
的全局 @ExceptionHandler
方法,在来自 @Controller
的局部方法之后被应用。相比之下,全局的 @ModelAttribute
和@InitBinder
方法会在本地方法之前应用。
@ControllerAdvice
注解有一些属性,可以让你缩小它们所适用的控制器和处理程序的集合。比如:
// 针对所有用 @RestController 注解的控制器
@ControllerAdvice(annotations = RestController.class)
public class ExampleAdvice1 {}
// 所有指定包中的控制器
@ControllerAdvice("org.example.controllers")
public class ExampleAdvice2 {}
// 所有指定的控制器
@ControllerAdvice(assignableTypes = {ControllerInterface.class, AbstractController.class})
public class ExampleAdvice3 {}
前面例子中的选择器是在运行时评估的,如果大量使用可能会对性能产生负面影响。更多细节请参见 @ControllerAdvice javadoc。