在 Spring Boot 项目中,全局异常处理器(Global Exception Handler) 是一种集中处理异常的机制,通过 @ControllerAdvice
或 @RestControllerAdvice
注解实现。以下是详细使用方法和执行时机的讲解:
一、全局异常处理器的核心作用
- 统一异常处理:避免在 Controller 中重复编写
try-catch
代码。 - 规范响应格式:对所有异常返回统一的 JSON 响应结构。
- 解耦异常处理:将异常处理逻辑从业务代码中分离。
二、实现全局异常处理器的步骤
1. 创建全局异常处理类
@RestControllerAdvice // 等同于 @ControllerAdvice + @ResponseBody
public class GlobalExceptionHandler {
// 日志记录(可选)
private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);
}
2. 处理特定异常(使用 @ExceptionHandler
)
// 处理自定义业务异常
@ExceptionHandler(BusinessException.class)
public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException ex) {
logger.error("业务异常: {}", ex.getMessage());
ErrorResponse error = new ErrorResponse(ex.getCode(), ex.getMessage());
return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}
// 处理所有未明确指定的异常
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleGlobalException(Exception ex) {
logger.error("系统异常: {}", ex.getMessage());
ErrorResponse error = new ErrorResponse("500", "系统繁忙,请稍后重试");
return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
}
3. 定义统一错误响应对象(可选)(根据你所要的返回格式来定义这个返回错误的类)
@Data
@AllArgsConstructor
public class ErrorResponse {
private String code;
private String message;
private LocalDateTime timestamp = LocalDateTime.now();
}
三、全局异常处理器的执行时机
- 触发条件:当 Controller 层抛出异常时,如果没有被
Controller
内部的@ExceptionHandler
处理,异常会向上抛到全局处理器。 - 执行顺序:
- Controller 内部的
@ExceptionHandler
优先处理。 - 若未处理,则由
@ControllerAdvice
全局处理器处理。
- Controller 内部的
- 异常匹配规则:
- 优先匹配最具体的异常类型(如
NullPointerException
优先于RuntimeException
)。 - 若没有匹配到具体异常,则执行
Exception.class
的通用处理。
- 优先匹配最具体的异常类型(如
四、扩展场景与最佳实践
1. 处理参数校验异常(结合 Validation)
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidationException(MethodArgumentNotValidException ex) {
String errorMsg = ex.getBindingResult()
.getFieldErrors()
.stream()
.map(FieldError::getDefaultMessage)
.collect(Collectors.joining(", "));
ErrorResponse error = new ErrorResponse("400", errorMsg);
return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}
2. 处理 404 资源不存在
@ExceptionHandler(NoHandlerFoundException.class)
public ResponseEntity<ErrorResponse> handle404(NoHandlerFoundException ex) {
ErrorResponse error = new ErrorResponse("404", "请求路径不存在");
return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
}
3. 自定义异常类(增强业务语义)
public class BusinessException extends RuntimeException {
private String code;
public BusinessException(String code, String message) {
super(message);
this.code = code;
}
}
五、关键注解说明
@ControllerAdvice
:扫描所有 Controller,结合@ExceptionHandler
使用。@RestControllerAdvice
:等同于@ControllerAdvice + @ResponseBody
,直接返回 JSON。@ExceptionHandler
:指定处理的异常类型,支持多个异常类。
六、测试验证
发送一个会触发异常的请求,观察返回的 JSON 是否符合预期格式(需要根据自己业务的开发来确定返回的错误信息的格式):
{
"code": "400",
"message": "参数校验失败",
"timestamp": "2023-10-05T15:30:00"
}
通过全局异常处理器,可以实现异常处理的集中化、规范化和解耦,是 Spring Boot 项目中异常管理的标准实践方案。