@ControllerAdvice介绍
@ControllerAdvice
是 Spring 框架提供的一个注解,用于定义一个全局的异常处理类或者说是控制器增强类(controller advice class)。这个特性特别适用于那些你想应用于整个应用程序中多个控制器的共有行为,比如全局异常处理、数据绑定、响应处理等。通过使用 @ControllerAdvice
,你可以避免在每个控制器中重复相同的代码,从而提高代码的可维护性和整洁性。
@ControllerAdvice源码
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {
@AliasFor(annotation = Component.class, attribute = "value")
String name() default "";
@AliasFor("basePackages")
String[] value() default {};
@AliasFor("value")
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
Class<?>[] assignableTypes() default {};
Class<? extends Annotation>[] annotations() default {};
}
源代码截图
@ControllerAdvice属性介绍
-
name()
: 这是一个继承自@Component
的属性,默认值为空字符串。可以为 Bean 指定一个名称,便于在 Spring 上下文中引用。 -
value()
和basePackages()
(以及它们之间的@AliasFor
): 这两个属性是等效的,用于指定哪些包下的控制器类应受此 advice 管理。默认值为空数组,意味着如果不指定,则对所有包的控制器生效。@ControllerAdvice(basePackages = {"com.chengxuyuan.controller"})。
-
basePackageClasses()
: 与指定包名不同,这个属性允许通过指定类来确定包的基点。Spring 会查找这些类所在的包及子包下的控制器应用此 advice。 -
assignableTypes()
: 允许你指定一个或多个类(类型数组),只有继承或实现了这些类的控制器才会受到此 advice 影响。@ControllerAdvice(assignableTypes = {DemoCustomController.class})。
-
annotations()
: 虽然你的代码示例中包含了此属性,但在 Spring Framework 的实际@ControllerAdvice
定义中,并没有直接包含annotations
属性来基于注解匹配控制器。这个概念可能源自于对 AOP 或其他自定义扩展方式的理解,但它不是标准@ControllerAdvice
的一部分。此属性用于说明如果要根据控制器上的特定注解来应用 advice,理论上可以通过自定义逻辑来实现
@ControllerAdvice注解使用场景
-
全局异常处理:
- 你可以结合
@ExceptionHandler
注解,在@ControllerAdvice
标注的类中定义方法来处理特定类型的异常。这些异常处理方法会应用到标记有@RequestMapping
的所有控制器方法上,从而实现全局异常处理机制。
- 你可以结合
-
模型属性添加:
- 使用
@ModelAttribute
注解可以在每次请求处理之前向模型中添加属性。这样,你可以在不修改每个控制器方法的情况下,为所有(或指定包下的)控制器添加共享数据。
- 使用
-
全局数据绑定和验证:
- 可以通过
@InitBinder
方法自定义数据绑定和验证逻辑,影响所有控制器中的数据绑定行为。
- 可以通过
-
响应体处理:
- 虽然不直接是
@ControllerAdvice
的一部分,但结合@ResponseBody
和ResponseEntity
,可以用来定制全局的响应体处理逻辑,比如统一设置响应头或响应状态码。
- 虽然不直接是
-
特定控制器或包的应用:
- 通过使用
basePackages
或assignableTypes
属性,可以指定@ControllerAdvice
应用于哪些特定的控制器或包下的控制器,而不是全局所有。
- 通过使用
@ControllerAdvice测试示例代码
示例代码 一
@ControllerAdvice
public class GlobalControllerAdvice {
/**
* 全局异常处理
*/
@ExceptionHandler(Exception.class)
public ModelAndView handleException(Exception ex) {
ModelAndView modelAndView = new ModelAndView("error");
modelAndView.addObject("errorMessage", ex.getMessage());
return modelAndView;
}
/**
* 全局数据绑定
*/
@InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
}
/**
* 全局模型属性
*/
@ModelAttribute("appName")
public String appName() {
return "Demo Application";
}
}