控制器建议

通常,@ExceptionHandler@InitBinder@ModelAttribute方法适用于声明它们的@Controller类(或类层次结构)内。如果您希望这些方法在更广泛的范围内适用(跨控制器),可以在一个使用@ControllerAdvice@RestControllerAdvice注解的类中声明它们。

@ControllerAdvice使用@Component注解,这意味着这样的类可以通过组件扫描注册为Spring bean。 @RestControllerAdvice是一个组合注解,它同时使用@ControllerAdvice@ResponseBody注解,这基本上意味着@ExceptionHandler方法通过消息转换呈现到响应体中(而不是视图解析或模板渲染)。

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

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

  • Java

  • Kotlin

// 目标是所有使用@RestController注解的控制器
@ControllerAdvice(annotations = RestController.class)
public class ExampleAdvice1 {}

// 目标是特定包内的所有控制器
@ControllerAdvice("org.example.controllers")
public class ExampleAdvice2 {}

// 目标是可分配给特定类的所有控制器
@ControllerAdvice(assignableTypes = {ControllerInterface.class, AbstractController.class})
public class ExampleAdvice3 {}
// 目标是所有使用@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以获取更多详细信息。