题目
Spring MVC中如何实现全局异常处理?请描述实现方式并举例说明
信息
- 类型:问答
- 难度:⭐⭐
考点
Spring MVC异常处理机制,@ControllerAdvice注解,@ExceptionHandler注解,全局异常处理最佳实践
快速回答
在Spring MVC中实现全局异常处理的核心步骤:
- 创建带有
@ControllerAdvice注解的全局异常处理类 - 在方法上使用
@ExceptionHandler注解指定处理的异常类型 - 在方法中定义异常处理逻辑和返回响应(如JSON或错误页面)
- 通过
ResponseEntity或@ResponseBody构建响应体
关键优势:统一处理控制器层异常,避免重复try-catch代码。
解析
1. 原理说明
Spring MVC通过@ControllerAdvice和@ExceptionHandler实现全局异常处理:
- @ControllerAdvice:标注的类会拦截所有控制器抛出的异常,可指定生效的包范围
- @ExceptionHandler:标注的方法处理特定异常,支持多种返回类型(ModelAndView, ResponseEntity, String等)
- 执行优先级:控制器内的
@ExceptionHandler> 全局@ControllerAdvice
2. 代码示例
@ControllerAdvice
public class GlobalExceptionHandler {
// 处理自定义业务异常
@ExceptionHandler(BusinessException.class)
public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException ex) {
ErrorResponse error = new ErrorResponse(
"BUSINESS_ERROR",
ex.getMessage(),
HttpStatus.BAD_REQUEST.value()
);
return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
}
// 处理所有未捕获异常
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleAllExceptions(Exception ex) {
ErrorResponse error = new ErrorResponse(
"SERVER_ERROR",
"Internal server error",
HttpStatus.INTERNAL_SERVER_ERROR.value()
);
return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
}
// 错误响应DTO
@Data
@AllArgsConstructor
private static class ErrorResponse {
private String code;
private String message;
private int status;
}
}3. 最佳实践
- 分层处理:定义不同
@ControllerAdvice处理特定模块异常 - 响应标准化:统一错误响应格式(如包含code/message/timestamp)
- 日志记录:在异常处理器中添加日志记录关键异常信息
- HTTP状态码匹配:根据异常类型返回合适的HTTP状态码(如400/404/500)
4. 常见错误
- 异常覆盖问题:多个处理器匹配时,Spring选择最精确的异常类型匹配
- 作用域未生效:
@ControllerAdvice(basePackages="com.example")需确保路径正确 - 循环依赖:避免在异常处理器中注入可能抛出异常的Bean
- 忽略原始异常:
@ExceptionHandler方法应记录原始异常堆栈
5. 扩展知识
- HandlerExceptionResolver接口:底层扩展点,可自定义解析器实现更复杂的异常处理逻辑
- @ResponseStatus:直接在自定义异常类上定义HTTP状态码(如
@ResponseStatus(HttpStatus.NOT_FOUND)) - Spring Boot增强:通过
ErrorController自定义/error端点处理容器级异常 - 与验证框架整合:处理
MethodArgumentNotValidException返回表单验证错误详情