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 {@Overridepublic Map<String, Object> getErrorAttributes(...) {Map<String, Object> map = super.getErrorAttributes(...);map.put("traceId", UUID.randomUUID().toString()); // 添加追踪IDreturn 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));}
}
四、最佳实践建议
-
分层处理
- 业务层抛出自定义异常(如
OrderNotFoundException
) - 控制器层专注参数校验和流程控制
- 全局处理器统一转换异常为响应
- 业务层抛出自定义异常(如
-
日志记录
在@ExceptionHandler
中记录错误堆栈:@ExceptionHandler(Exception.class) public ResponseEntity<ErrorResponse> handleException(Exception ex, HttpServletRequest request) {log.error("Request {} failed: {}", request.getRequestURI(), ex.getMessage(), ex);// ...返回响应 }
-
前端友好
返回标准化错误码(如1001=用户不存在
),便于前端识别处理。
五、完整项目结构示例
src/main/java/
├── exception/
│ ├── GlobalExceptionHandler.java # 全局处理器
│ ├── BusinessException.java # 自定义业务异常
│ └── ErrorResponse.java # 错误响应体
└── config/└── CustomErrorAttributes.java # 错误属性扩展