Spring Boot实现异常处理

发布于:2025-06-23 ⋅ 阅读:(20) ⋅ 点赞:(0)

Spring Boot 提供了多种灵活的方式实现异常处理,以下是核心方案和最佳实践:


一、基础异常处理方案

1. @ControllerAdvice + @ExceptionHandler(全局处理)
@ControllerAdvice
public class GlobalExceptionHandler {
    
    // 处理特定异常(如业务异常)
    @ExceptionHandler(BusinessException.class)
    public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException ex) {
        ErrorResponse error = new ErrorResponse(ex.getCode(), ex.getMessage());
        return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
    }

    // 处理所有未捕获异常
    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleAllExceptions(Exception ex) {
        ErrorResponse error = new ErrorResponse("500", "服务器内部错误");
        return new ResponseEntity<>(error, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

// 自定义错误响应体
@Data
class ErrorResponse {
    private String code;
    private String message;
    // 可扩展时间戳、路径等字段
}

作用

  • 捕获控制器层抛出的所有异常,返回结构化错误信息
  • 支持区分异常类型定制HTTP状态码和响应体
2. @ResponseStatus(简单场景)
@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "资源不存在")
public class ResourceNotFoundException extends RuntimeException {
    // 自动返回404状态码和指定消息
}

二、REST API 增强处理

1. 自定义错误数据结构
{
  "timestamp": "2025-06-22T10:00:00",
  "status": 404,
  "error": "Not Found",
  "path": "/api/users/999"
}

通过继承 DefaultErrorAttributes 可扩展字段:

@Component
public class CustomErrorAttributes extends DefaultErrorAttributes {
    @Override
    public Map<String, Object> getErrorAttributes(...) {
        Map<String, Object> map = super.getErrorAttributes(...);
        map.put("traceId", UUID.randomUUID().toString()); // 添加追踪ID
        return map;
    }
}
2. OpenAPI/Swagger 集成

@ControllerAdvice 中补充注解:

@Operation(responses = {
    @ApiResponse(responseCode = "400", description = "业务参数错误"),
    @ApiResponse(responseCode = "500", description = "系统内部错误")
})

三、特殊场景处理

1. 校验异常处理(Validation)

自动捕获 MethodArgumentNotValidException

@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidationExceptions(MethodArgumentNotValidException ex) {
    String errorMsg = ex.getBindingResult()
                      .getFieldErrors()
                      .stream()
                      .map(FieldError::getDefaultMessage)
                      .collect(Collectors.joining(", "));
    return new ResponseEntity<>(new ErrorResponse("400", errorMsg), HttpStatus.BAD_REQUEST);
}
2. Servlet 容器级错误

配置 ErrorController 处理404等底层错误:

@RestController
public class CustomErrorController implements ErrorController {
    
    @RequestMapping("/error")
    public ResponseEntity<ErrorResponse> handleError(HttpServletRequest request) {
        Integer status = (Integer) request.getAttribute("javax.servlet.error.status_code");
        return new ResponseEntity<>(new ErrorResponse(status.toString(), "请求路径不存在"), HttpStatus.valueOf(status));
    }
}

四、最佳实践建议

  1. 分层处理

    • 业务层抛出自定义异常(如 OrderNotFoundException
    • 控制器层专注参数校验和流程控制
    • 全局处理器统一转换异常为响应
  2. 日志记录
    @ExceptionHandler 中记录错误堆栈:

    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleException(Exception ex, HttpServletRequest request) {
        log.error("Request {} failed: {}", request.getRequestURI(), ex.getMessage(), ex);
        // ...返回响应
    }
    
  3. 前端友好
    返回标准化错误码(如 1001=用户不存在),便于前端识别处理。


五、完整项目结构示例

src/main/java/
├── exception/
│   ├── GlobalExceptionHandler.java  # 全局处理器
│   ├── BusinessException.java       # 自定义业务异常
│   └── ErrorResponse.java           # 错误响应体
└── config/
    └── CustomErrorAttributes.java   # 错误属性扩展

网站公告

今日签到

点亮在社区的每一天
去签到