业务异常与全局异常处理
Forge 通过自定义异常和全局异常处理器统一管理错误响应。你需要在 Service 层抛出业务异常,由全局处理器转换为 RespInfo。
自定义业务异常
java
public class BusinessException extends RuntimeException {
private int code;
private String message;
public BusinessException(String message) {
super(message);
this.code = 500;
this.message = message;
}
public BusinessException(int code, String message) {
super(message);
this.code = code;
this.message = message;
}
}使用方式
在 Service 层抛出业务异常:
java
@Service
public class OrderServiceImpl implements OrderService {
@Override
public OrderVO create(OrderDTO dto) {
// 校验订单号唯一
if (orderMapper.selectByOrderNo(dto.getOrderNo()) != null) {
throw new BusinessException("订单号已存在");
}
// 校验金额
if (dto.getAmount() <= 0) {
throw new BusinessException(400, "金额必须大于0");
}
OrderEntity entity = new OrderEntity();
BeanUtils.copyProperties(dto, entity);
orderMapper.insert(entity);
return toVO(entity);
}
}全局异常处理
GlobalExceptionHandler 使用 @RestControllerAdvice 捕获异常:
java
@RestControllerAdvice
public class GlobalExceptionHandler {
// 业务异常
@ExceptionHandler(BusinessException.class)
public RespInfo handleBusiness(BusinessException e) {
log.warn("业务异常: {}", e.getMessage());
return RespInfo.error(e.getCode(), e.getMessage());
}
// 参数校验异常
@ExceptionHandler(MethodArgumentNotValidException.class)
public RespInfo handleValidation(MethodArgumentNotValidException e) {
String message = e.getBindingResult().getFieldErrors().stream()
.map(f -> f.getField() + ": " + f.getDefaultMessage())
.collect(Collectors.joining("; "));
return RespInfo.error(400, message);
}
// 权限异常
@ExceptionHandler(NotPermissionException.class)
public RespInfo handlePermission(NotPermissionException e) {
return RespInfo.error(403, "无权限访问");
}
// 认证异常
@ExceptionHandler(NotLoginException.class)
public RespInfo handleLogin(NotLoginException e) {
return RespInfo.error(401, "未登录或登录已过期");
}
// 兜底异常
@ExceptionHandler(Exception.class)
public RespInfo handleException(Exception e) {
log.error("系统异常", e);
return RespInfo.error(500, "系统异常,请联系管理员");
}
}错误码定义
建议在常量类中统一定义错误码:
java
public class ErrorCode {
public static final int SUCCESS = 200;
public static final int BAD_REQUEST = 400;
public static final int UNAUTHORIZED = 401;
public static final int FORBIDDEN = 403;
public static final int SERVER_ERROR = 500;
// 业务错误码 1xxx
public static final int ORDER_NOT_FOUND = 1001;
public static final int ORDER_STATUS_ERROR = 1002;
public static final int ORDER_ALREADY_PAID = 1003;
}使用:
java
throw new BusinessException(ErrorCode.ORDER_NOT_FOUND, "订单不存在");异常处理流程
Service 抛出 BusinessException
↓
GlobalExceptionHandler 捕获
↓
转换为 RespInfo.error(code, msg)
↓
返回前端 JSON注意事项
- 不要在 Controller 层 try-catch 吞异常,让全局处理器统一处理
- 业务异常用
BusinessException,不要用RuntimeException - 日志级别:业务异常用
warn,系统异常用error - 异常消息:面向用户,不要暴露技术细节(如堆栈信息)
