在SpringBoot应用开发中,统一异常处理是构建健壮系统的关键环节。默认异常处理机制往往无法满足复杂业务场景的需求,自定义异常处理能让错误信息更具业务语义,提升系统可维护性。本文将深入剖析SpringBoot自定义异常的底层原理,并通过实战案例演示实现方法。
SpringBoot异常处理基于以下核心组件:
@ResponseStatus
注解的异常@ExceptionHandler
注解的方法Controller方法抛出异常 → DispatcherServlet捕获异常 →
遍历HandlerExceptionResolver链 → 找到匹配的异常处理器 →
执行异常处理逻辑 → 返回ResponseEntity
// 基础业务异常
public class BusinessException extends RuntimeException {
private final int code; // 错误码
private final String message; // 错误信息
public BusinessException(ErrorCode errorCode) {
this.code = errorCode.getCode();
this.message = errorCode.getMessage();
}
public BusinessException(int code, String message) {
this.code = code;
this.message = message;
}
// getter方法
}
// 错误码枚举
public enum ErrorCode {
USER_NOT_FOUND(1001, "用户不存在"),
INVALID_PARAM(1002, "参数无效"),
ORDER_CLOSED(2001, "订单已关闭");
private final int code;
private final String message;
ErrorCode(int code, String message) {
this.code = code;
this.message = message;
}
// getter方法
}
@Service
public class UserService {
public UserDTO getUserById(Long userId) {
User user = userRepository.findById(userId)
.orElseThrow(() -> new BusinessException(ErrorCode.USER_NOT_FOUND));
return convertToDTO(user);
}
}
@ControllerAdvice
public class GlobalExceptionHandler {
// 处理业务异常
@ExceptionHandler(BusinessException.class)
public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException e) {
ErrorResponse response = new ErrorResponse(e.getCode(), e.getMessage());
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response);
}
// 处理未预期异常
@ExceptionHandler(Exception.class)
public ResponseEntity<ErrorResponse> handleUnexpectedException(Exception e) {
ErrorResponse response = new ErrorResponse(5000, "系统内部错误");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}
// 统一错误响应格式
@Data
@AllArgsConstructor
public class ErrorResponse {
private int code;
private String message;
private LocalDateTime timestamp = LocalDateTime.now();
}
@Service
public class OrderService {
public void processOrder(Long orderId) {
try {
// 调用外部服务
paymentService.charge(orderId);
} catch (PaymentException e) {
// 包装原始异常,保留堆栈信息
throw new BusinessException(4001, "支付失败", e);
}
}
}
public class UserOperationException extends BusinessException {
private final String userId;
private final String operation;
public UserOperationException(String userId, String operation, String message) {
super(1003, message);
this.userId = userId;
this.operation = operation;
}
// getter方法
}
@ExceptionHandler(BusinessException.class)
public ResponseEntity<ErrorResponse> handleBusinessException(BusinessException e, HttpServletRequest request) {
// 记录详细日志
log.error("业务异常: [{}] {}, 请求路径: {}",
e.getCode(), e.getMessage(), request.getRequestURI());
return ResponseEntity.status(HttpStatus.BAD_REQUEST)
.body(new ErrorResponse(e.getCode(), e.getMessage()));
}
@Controller
public class CustomErrorController implements ErrorController {
@RequestMapping("/error")
public String handleError(HttpServletRequest request) {
Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
if (status != null) {
int statusCode = Integer.parseInt(status.toString());
if (statusCode == HttpStatus.NOT_FOUND.value()) {
return "error/404";
} else if (statusCode == HttpStatus.INTERNAL_SERVER_ERROR.value()) {
return "error/500";
}
}
return "error/general";
}
}
src/main/resources/templates/error
目录下// 控制器层:处理HTTP相关异常
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<ErrorResponse> handleValidationException(MethodArgumentNotValidException e) {
String errorMsg = e.getBindingResult().getFieldErrors()
.stream()
.map(fieldError -> fieldError.getField() + ": " + fieldError.getDefaultMessage())
.collect(Collectors.joining(", "));
return ResponseEntity.badRequest().body(new ErrorResponse(4000, errorMsg));
}
// 服务层:处理业务逻辑异常
@Service
public class UserService {
public void updateUser(UserDTO userDTO) {
if (!isValidEmail(userDTO.getEmail())) {
throw new BusinessException(ErrorCode.INVALID_EMAIL);
}
// 业务逻辑
}
}
SpringBoot自定义异常处理是构建高质量应用的关键技术,通过合理设计异常体系和统一处理机制,可以:
核心实现步骤包括:定义业务异常类、创建全局异常处理器、设计统一响应格式,并根据业务需求扩展高级功能。遵循最佳实践可以构建出既健壮又易于维护的SpringBoot应用。