Java自定义业务异常类

一、类的作用

核心功能:

  1. 封装业务异常信息 - 包含错误码和错误消息

  2. 继承RuntimeException - 属于非受检异常,不需要强制捕获

  3. 统一异常格式 - 在整个应用中保持一致的异常处理方式

设计特点:

  • 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();

五、注意事项

  1. 不要滥用:仅在业务逻辑错误时使用,技术异常(如数据库连接失败)建议用原生异常

  2. 错误码规划

    • 4xx: 客户端错误(400参数错误、403无权限、404不存在)

    • 5xx: 服务端错误

  3. 国际化支持:如需多语言,可考虑扩展消息为消息键

  4. 日志记录:在全局异常处理器中记录异常日志

六、扩展建议

如果需要更丰富的功能,可以考虑:

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,技术异常用原生异常"的原则,能显著提高代码的可维护性和异常处理的规范性。

相关推荐
达文汐12 小时前
【困难】力扣算法题解析LeetCode332:重新安排行程
java·数据结构·经验分享·算法·leetcode·力扣
培风图南以星河揽胜12 小时前
Java版LeetCode热题100之零钱兑换:动态规划经典问题深度解析
java·leetcode·动态规划
启山智软12 小时前
【中大企业选择源码部署商城系统】
java·spring·商城开发
我真的是大笨蛋13 小时前
深度解析InnoDB如何保障Buffer与磁盘数据一致性
java·数据库·sql·mysql·性能优化
怪兽源码13 小时前
基于SpringBoot的选课调查系统
java·spring boot·后端·选课调查系统
恒悦sunsite13 小时前
Redis之配置只读账号
java·redis·bootstrap
梦里小白龙13 小时前
java 通过Minio上传文件
java·开发语言
人道领域13 小时前
javaWeb从入门到进阶(SpringBoot事务管理及AOP)
java·数据库·mysql
sheji526114 小时前
JSP基于信息安全的读书网站79f9s--程序+源码+数据库+调试部署+开发环境
java·开发语言·数据库·算法
毕设源码-邱学长14 小时前
【开题答辩全过程】以 基于Java Web的电子商务网站的用户行为分析与个性化推荐系统为例,包含答辩的问题和答案
java·开发语言