Spring Boot 提供了多种灵活的方式实现异常处理,以下是核心方案和最佳实践:
@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;
// 可扩展时间戳、路径等字段
}
作用:
@ResponseStatus
(简单场景)@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "资源不存在")
public class ResourceNotFoundException extends RuntimeException {
// 自动返回404状态码和指定消息
}
{
"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;
}
}
在 @ControllerAdvice
中补充注解:
@Operation(responses = {
@ApiResponse(responseCode = "400", description = "业务参数错误"),
@ApiResponse(responseCode = "500", description = "系统内部错误")
})
自动捕获 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);
}
配置 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 # 错误属性扩展