侧边栏壁纸
博主头像
colo

欲买桂花同载酒

  • 累计撰写 1823 篇文章
  • 累计收到 0 条评论

Spring MVC中如何实现全局异常处理?

2025-12-5 / 0 评论 / 4 阅读

题目

Spring MVC中如何实现全局异常处理?

信息

  • 类型:问答
  • 难度:⭐⭐

考点

异常处理机制,@ControllerAdvice注解,@ExceptionHandler注解,最佳实践

快速回答

在Spring MVC中实现全局异常处理的核心步骤:

  • 创建带有@ControllerAdvice注解的全局异常处理器类
  • 在方法上使用@ExceptionHandler注解指定处理的异常类型
  • 在方法中定义异常处理逻辑和返回响应(如ModelAndView、ResponseEntity等)
  • 结合@ResponseStatus注解自定义HTTP状态码
## 解析

一、原理说明

Spring MVC通过DispatcherServlet统一处理请求,当控制器抛出异常时:

  1. 查找当前控制器内的@ExceptionHandler方法
  2. 若未找到,查找@ControllerAdvice标注的全局异常处理器
  3. 调用匹配的异常处理方法生成响应

@ControllerAdvice作为组件扫描的全局拦截器,可结合basePackages/annotations限定作用范围。

二、代码示例

@ControllerAdvice
public class GlobalExceptionHandler {

    // 处理特定异常
    @ExceptionHandler(CustomBusinessException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ResponseEntity<ErrorResponse> handleBusinessException(CustomBusinessException ex) {
        ErrorResponse error = new ErrorResponse(
            "BUSINESS_ERROR", 
            ex.getMessage(),
            Instant.now()
        );
        return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
    }

    // 处理所有未捕获异常
    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public ResponseEntity<ErrorResponse> handleAllExceptions(Exception ex) {
        ErrorResponse error = new ErrorResponse(
            "SERVER_ERROR", 
            "Internal server error",
            Instant.now()
        );
        return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

// 错误响应DTO
public class ErrorResponse {
    private String code;
    private String message;
    private Instant timestamp;
    // 构造方法/getter/setter省略
}

三、最佳实践

  1. 分层处理:业务异常(如CustomBusinessException)和系统异常分开处理
  2. 统一响应格式:所有异常返回标准化JSON结构(包含错误码、消息、时间戳)
  3. HTTP状态码:通过@ResponseStatusResponseEntity设置符合语义的状态码
  4. 日志记录:在全局处理器中记录ERROR级别日志
  5. 避免泄露细节:生产环境中隐藏堆栈信息,防止安全风险

四、常见错误

  • 作用域问题:未将@ControllerAdvice类放入Spring扫描路径
  • 异常匹配顺序@ExceptionHandler方法按精确度优先匹配,将Exception.class放在最后
  • 响应冲突:同时使用@ResponseBodyResponseEntity导致重复包装
  • 忽略事务回滚:默认仅对RuntimeException回滚,需用@Transactional(rollbackFor=Exception.class)

五、扩展知识

  • HandlerExceptionResolver接口:底层扩展点,可自定义解析器实现更复杂的异常处理逻辑
  • ErrorController:处理404等非异常HTTP错误,需实现ErrorController接口并重写getErrorPath()
  • Spring Boot增强:通过ErrorAttributes定制错误属性,或使用@RestControllerAdvice替代@ControllerAdvice(默认含@ResponseBody
  • 异步请求处理:异步方法需在CallableDeferredResult内抛异常才能被全局处理器捕获