一、类的作用
核心功能:
-
封装业务异常信息 - 包含错误码和错误消息
-
继承RuntimeException - 属于非受检异常,不需要强制捕获
-
统一异常格式 - 在整个应用中保持一致的异常处理方式
设计特点:
-
code: 自定义错误码,用于前端识别错误类型 -
message: 错误描述信息 -
支持两种枚举类型(RespStatus和ResponseStatus)的异常构造
二、构造方法详解
java
// 1. 指定错误码和消息
new BusinessException(400, "参数错误")
// 2. 使用RespStatus枚举(推荐)
new BusinessException(RespStatus.ERROR)
// 3. 仅提供消息,默认500错误码
new BusinessException("系统内部错误")
// 4. 带原始异常的构造
new BusinessException(400, "处理失败", originalException)
// 5. 使用ResponseStatus枚举
new BusinessException(ResponseStatus.SUCCESS)
// 6. 带异常的ResponseStatus
new BusinessException(ResponseStatus.ERROR, originalException)
三、实际应用示例
场景1:在Service层使用
java
@Service
public class UserService {
public User getUserById(Long id) {
User user = userRepository.findById(id);
if (user == null) {
// 使用枚举方式
throw new BusinessException(RespStatus.USER_NOT_FOUND);
// 或使用代码+消息方式
throw new BusinessException(404, "用户不存在");
}
return user;
}
public void updateSalary(Long userId, BigDecimal amount) {
if (amount.compareTo(BigDecimal.ZERO) < 0) {
throw new BusinessException(ResponseStatus.INVALID_PARAM);
}
// 业务逻辑...
}
}
场景2:在Controller层处理
java
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(BusinessException.class)
public Result<Void> handleBusinessException(BusinessException e) {
return Result.error(e.getCode(), e.getMessage());
}
@ExceptionHandler(Exception.class)
public Result<Void> handleOtherException(Exception e) {
return Result.error(500, "系统异常");
}
}
场景3:定义和使用枚举
java
// RespStatus枚举示例
public enum RespStatus {
SUCCESS(200, "成功"),
ERROR(500, "系统错误"),
USER_NOT_FOUND(404, "用户不存在"),
PARAM_ERROR(400, "参数错误"),
FORBIDDEN(403, "无权限访问");
private final Integer code;
private final String desc;
// 构造方法、getter...
}
// 使用示例
public class OrderService {
public void createOrder(OrderDTO dto) {
if (dto.getAmount() <= 0) {
throw new BusinessException(RespStatus.PARAM_ERROR);
}
}
}
四、最佳实践建议
1. 分层使用
java
// Controller层:参数校验
@PostMapping("/create")
public Result create(@Valid @RequestBody UserDTO dto) {
if (dto.getAge() < 18) {
throw new BusinessException(400, "年龄必须大于18岁");
}
}
// Service层:业务校验
public void transfer(Long from, Long to, BigDecimal amount) {
Account fromAccount = accountRepository.findById(from);
if (fromAccount.getBalance().compareTo(amount) < 0) {
throw new BusinessException(ResponseStatus.INSUFFICIENT_BALANCE);
}
}
// Repository层:建议使用原生异常
public User findUser(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new BusinessException(RespStatus.USER_NOT_FOUND));
}
2. 统一返回格式
java
@Data
public class Result<T> {
private Integer code;
private String message;
private T data;
public static <T> Result<T> success(T data) {
Result<T> result = new Result<>();
result.setCode(200);
result.setMessage("成功");
result.setData(data);
return result;
}
public static <T> Result<T> error(Integer code, String message) {
Result<T> result = new Result<>();
result.setCode(code);
result.setMessage(message);
return result;
}
}
3. 创建业务异常工厂(可选)
java
public class BusinessExceptionFactory {
public static BusinessException userNotFound() {
return new BusinessException(RespStatus.USER_NOT_FOUND);
}
public static BusinessException insufficientBalance() {
return new BusinessException(400, "余额不足");
}
public static BusinessException parameterError(String field) {
return new BusinessException(400, field + "参数错误");
}
}
// 使用
throw BusinessExceptionFactory.userNotFound();
五、注意事项
-
不要滥用:仅在业务逻辑错误时使用,技术异常(如数据库连接失败)建议用原生异常
-
错误码规划:
-
4xx: 客户端错误(400参数错误、403无权限、404不存在)
-
5xx: 服务端错误
-
-
国际化支持:如需多语言,可考虑扩展消息为消息键
-
日志记录:在全局异常处理器中记录异常日志
六、扩展建议
如果需要更丰富的功能,可以考虑:
java
// 扩展类示例
public class EnhancedBusinessException extends BusinessException {
private Map<String, Object> data;
private String errorType;
public EnhancedBusinessException(Integer code, String message) {
super(code, message);
}
// 添加额外数据
public EnhancedBusinessException withData(Map<String, Object> data) {
this.data = data;
return this;
}
}
总结
这个**BusinessException** 类是业务异常的统一封装,通过:
-
标准化错误码和消息格式
-
支持多种构造方式
-
便于全局异常处理
使用时遵循"业务异常用BusinessException,技术异常用原生异常"的原则,能显著提高代码的可维护性和异常处理的规范性。