@RestControllerAdvice 业务案例场景
@RestControllerAdvice
注解,用于定义一个类,该类可以全局处理多个控制器的异常以及封装响应数据。它通常与 @ExceptionHandler
、@InitBinder
和 @ModelAttribute
注解结合使用,以实现集中式异常处理和模型属性的初始化。
注解结构:
业务场景:
例如你正在开发一个大型的 Web 应用程序,该程序包含许多不同的控制器,这些控制器可能会抛出各种异常。为了统一处理这些异常并返回统一格式的响应数据,你可以使用 @RestControllerAdvice
。
1. 创建全局异常处理器:
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.http.HttpStatus;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
// 处理自定义异常
@ExceptionHandler(CustomNotFoundException.class)
public ResponseEntity<Object> handleCustomNotFoundException(CustomNotFoundException ex) {
ErrorDetails errorDetails = new ErrorDetails(new Date(), ex.getMessage());
return new ResponseEntity<>(errorDetails, HttpStatus.NOT_FOUND);
}
// 处理所有未捕获的异常
@ExceptionHandler(Exception.class)
public ResponseEntity<Object> handleAllExceptions(Exception ex) {
ErrorDetails errorDetails = new ErrorDetails(new Date(), "Internal Server Error");
return new ResponseEntity<>(errorDetails, HttpStatus.INTERNAL_SERVER_ERROR);
}
// 可以添加更多的异常处理方法...
}
class ErrorDetails {
private Date timestamp;
private String message;
public ErrorDetails(Date timestamp, String message) {
this.timestamp = timestamp;
this.message = message;
}
// 标准的 getter 和 setter
}
在这个例子中,GlobalExceptionHandler
类使用 @RestControllerAdvice
注解,表示它是一个全局异常处理器。@ExceptionHandler
注解的方法可以捕获并处理特定类型的异常。
2. 定义自定义异常:
public class CustomNotFoundException extends RuntimeException {
public CustomNotFoundException(String message) {
super(message);
}
}
3. 控制器中抛出异常:
@RestController
@RequestMapping("/api")
public class ApiController {
@GetMapping("/items/{id}")
public Item getItem(@PathVariable Long id) {
Item item = itemService.findById(id);
if (item == null) {
throw new CustomNotFoundException("Item with id " + id + " not found");
}
return item;
}
}
在这个控制器中,如果请求的资源不存在,将抛出 CustomNotFoundException
异常。
4. 异常处理和响应:
当控制器抛出异常时,GlobalExceptionHandler
中相应的 @ExceptionHandler
方法将捕获并处理异常,返回一个包含错误详情和 HTTP 状态码的响应。
5. 注解属性说明:
@RestControllerAdvice
注解的主要属性及其说明:
-
basePackages:
- 类型:
String[]
- 作用:指定控制器所在的基础包。
@RestControllerAdvice
注解的类将只对这些包或其子包中的控制器有效。
- 类型:
-
basePackageClasses:
- 类型:
Class<?>[]
- 作用:类型安全的替代
basePackages
,用于指定控制器所在的包。可以通过引用包中的特定类来实现。
- 类型:
-
assignableTypes:
- 类型:
Class<?>[]
- 作用:指定控制器的类型。
@RestControllerAdvice
注解的类将对所有可以被assignableTypes
中的类所处理的控制器提供建议。
- 类型:
-
annotations:
- 类型:
Class<? extends Annotation>[]
- 作用:指定注解类型。
@RestControllerAdvice
注解的类将对所有被annotations
中指定的注解所注解的控制器提供建议。
- 类型:
-
order:
- 类型:
int
- 作用:指定
@RestControllerAdvice
类的顺序值。这个值决定了多个@RestControllerAdvice
类的执行顺序,数值越小,优先级越高。
- 类型:
-
value:
- 类型:
String[]
- 作用:与
basePackages
相同,是basePackages
的别名,用于指定控制器所在的基础包。
- 类型:
限制作用用法:
@RestControllerAdvice(basePackages = "com.example.myapp.controllers")
public class GlobalExceptionHandler {
// 异常处理、模型属性初始化等方法
}
在这个示例中,@RestControllerAdvice
注解的 basePackages
属性用于指定该异常处理器应该应用于 com.example.myapp.controllers
包及其子包中的控制器。
总结:
@RestControllerAdvice
允许开发者集中处理应用程序中的异常,而不是在每个控制器中单独处理。- 它提供了一种机制来统一异常响应的格式,使得返回给客户端的错误信息更加一致和易于理解。
- 使用
@RestControllerAdvice
可以提高代码的复用性和可维护性,尤其是当应用程序中的异常处理逻辑较为复杂时。
转载自:https://juejin.cn/post/7383029376381861925