目录
-
- 简介
- 基本用法
- 注解参数
-
- [1.value(): String[]](#1.value(): String[])
- [2.basePackages(): String[]](#2.basePackages(): String[])
- [3.basePackageClasses(): Class<?>[]](#3.basePackageClasses(): Class<?>[])
- [4.assignableTypes(): Class<?>[]](#4.assignableTypes(): Class<?>[])
- [5.annotations(): Class<? extends Annotation>[]](#5.annotations(): Class<? extends Annotation>[])
- 三.注解组成
- 总结
简介
@ControllerAdvice
是 Spring 框架中提供的一个注解,用于定义一个组件,该组件可以集中处理来自不同控制器的异常或提供统一的拦截器功能。它主要用于以下几个方面:
- 全局异常处理 :通过结合
@ExceptionHandler
注解,可以捕获和处理在控制器中抛出的异常。 - 全局拦截器 :通过实现
HandlerInterceptor
接口,并在类上使用@ControllerAdvice
注解,可以实现一个全局的拦截器,对控制器的方法调用进行拦截。 - 全局数据绑定 :通过结合
@InitBinder
注解,可以在控制器方法执行前对数据绑定进行预处理。
基本用法
全局异常处理
假设我们想要捕获并统一处理所有控制器抛出的 ArithmeticException
异常:
java
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ArithmeticException.class)
public ResponseEntity<Object> handleArithmeticException(ArithmeticException ex) {
// 定义错误信息
ApiError apiError = new ApiError("An arithmetic error occurred", ex.getMessage());
// 返回错误响应
return new ResponseEntity<>(apiError, HttpStatus.BAD_REQUEST);
}
}
在这个例子中,任何控制器抛出的 ArithmeticException
都会被 GlobalExceptionHandler
类中的 handleArithmeticException
方法捕获,并返回一个包含错误信息的响应。
全局拦截器
创建一个全局拦截器来记录每个请求的处理时间:
java
@ControllerAdvice
public class LoggingInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("PreHandle: " + request.getRequestURI());
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
System.out.println("PostHandle: " + request.getRequestURI());
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
long timeTaken = System.currentTimeMillis() - request.getAttribute("startTime") == null ? 0 : (Long) request.getAttribute("startTime");
System.out.println("AfterCompletion: " + request.getRequestURI() + ", Time Taken: " + timeTaken + "ms");
}
}
在 preHandle
方法中,你可以在控制器方法执行前进行一些操作,例如记录开始时间。postHandle
方法在控制器方法执行后执行,而 afterCompletion
方法在视图渲染后执行,适合用于记录请求处理的总时间。
全局数据绑定
自定义数据绑定:
java
@ControllerAdvice
public class MyDataBinder {
@InitBinder
public void initBinder(WebDataBinder binder) {
// 可以在这里自定义属性编辑器
binder.registerCustomEditor(MyObject.class, new MyObjectEditor());
}
}
在这个例子中,我们通过 @InitBinder
注解定义了一个方法,该方法将在每个控制器方法调用之前执行,用于注册自定义的数据绑定行为。
注解参数
1.value(): String[]
用于指定要应用通知的包名。
例如:@ControllerAdvice("org.example.controllers")
2.basePackages(): String[]
与 value() 相同,用于指定要应用通知的包名。
例如:@ControllerAdvice(basePackages = "org.example.controllers")
3.basePackageClasses(): Class<?>[]
用于指定要应用通知的基础包类。
例如:@ControllerAdvice(basePackageClasses = MyController.class)
4.assignableTypes(): Class<?>[]
用于指定要应用通知的特定类型。
例如:@ControllerAdvice(assignableTypes = {ControllerInterface.class, AbstractController.class})
5.annotations(): Class<? extends Annotation>[]
用于指定要应用通知的注解类型。
例如:@ControllerAdvice(annotations = RestController.class)
三.注解组成
@ControllerAdvice 实际上是一个组合注解(meta-annotation),它由几个其他的 Spring 注解组成。
@ControllerAdvice 的注解定义大致如下:
java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ControllerAdvice {
// ... 参数定义
}
从这个定义中,我们可以看到 @ControllerAdvice 主要由以下注解组成:
-
@Target(ElementType.TYPE)
指定该注解可以应用于类级别。
-
@Retention(RetentionPolicy.RUNTIME)
指定该注解在运行时可用。
-
@Documented
表示该注解应该被包含在 JavaDoc 中。
-
@Component
这是最关键的组成部分。@Component 使得被 @ControllerAdvice 注解的类成为 Spring 容器管理的一个组件。
@Component 的存在意味着:
- @ControllerAdvice 注解的类会被自动检测并注册为 Spring Bean。
- 它允许该类被 Spring 的组件扫描机制识别和管理。
虽然 @ControllerAdvice 本身并不直接包含如 @ExceptionHandler、@InitBinder 或 @ModelAttribute 这样的功能性注解,但它为这些注解提供了一个全局的应用上下文。当与这些注解结合使用时,@ControllerAdvice 使得它们的作用范围扩展到了多个控制器。
重要的是要注意,@ControllerAdvice 本身并不提供任何具体的功能。它主要作为一个标记,告诉 Spring 框架这个类应该被特殊处理,允许其中的方法(通过其他注解如 @ExceptionHandler 等标记)应用于多个控制器。
总结
@ControllerAdvice 主要是通过 @Component 注解实现其核心功能,而其他的元注解(@Target, @Retention, @Documented)则提供了额外的元数据信息。这种组合使得 @ControllerAdvice 成为一个强大而灵活的工具,用于在 Spring MVC 应用中实现全局的控制器相关功能。