先要明白
@GetMapping("/user/{id}")
public User getUser(@PathVariable Long id) {
return userService.getById(id);
}
我用生活中的例子解释 @RestControllerAdvice 的工作原理:
想象一个大型商场的客服中心:
- DispatcherServlet就像商场的总服务台
- @RestControllerAdvice就像商场的客服中心
- 设立在商场的一个统一位置
- 专门处理各个专柜出现的问题和投诉
举个具体场景:
顾客在商场购物的流程:
1. 正常流程:
顾客 -> 总服务台(DispatcherServlet) -> 专柜(Controller) -> 购买商品
2. 出现问题时:
专柜(Controller)出现问题 -> 客服中心(@RestControllerAdvice)接手处理 -> 给顾客一个合理解释
用代码表示:
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(ProductOutOfStockException.class)
public ResponseEntity<String> handleOutOfStock(ProductOutOfStockException e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body("商品暂时缺货,预计3天后到货");
}
@ExceptionHandler(PriceException.class)
public ResponseEntity<String> handlePriceError(PriceException e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body("价格显示异常,请稍后重试");
}
}
为什么能拦截异常?
就像商场里:
- 所有专柜都在商场里面
- 客服中心在商场的入口处
- 一旦专柜出问题,就会按照商场规定,统一转到客服中心处理
在Spring中:
- DispatcherServlet(总服务台)知道有这个@RestControllerAdvice(客服中心)的存在
- 当Controller(专柜)抛出异常时
- DispatcherServlet就会把异常转给@RestControllerAdvice处理
关键点:
- 它不是拦截,而是异常发生后的统一处理
- Spring框架帮我们做了这个转发操作
- 这样我们就不用在每个Controller里写重复的异常处理代码