应抛出业务异常 couponunavailableexception:定义继承 runtimeexception 的自定义异常类,服务层前置校验券状态、时效与库存并主动抛出,通过 @controlleradvice 统一处理为标准错误码响应,辅以单元测试覆盖过期、库存耗尽等边界场景。

在 Java 项目中,当用户尝试领取或使用优惠券时,若该券已过期或库存已领完,应明确抛出业务异常 CouponUnavailableException,而非用通用异常(如 RuntimeException)或返回错误码掩盖问题。这有助于分层处理、日志追踪和前端友好提示。
定义清晰的业务异常类
创建一个受检或非受检的自定义异常,推荐继承 RuntimeException(避免强制 try-catch,符合多数业务场景):
public class CouponUnavailableException extends RuntimeException {
public CouponUnavailableException(String message) {
super(message);
}
public CouponUnavailableException(String message, Throwable cause) {
super(message, cause);
}
}
可进一步扩展为带错误码的结构化异常(如含 errorCode 字段),便于统一网关拦截并转成标准响应体。
在服务层主动校验并抛出
不要等到 DAO 层扣减失败才处理。应在 Service 方法开头做前置校验:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 查优惠券是否存在且状态为「可用」
- 比对当前时间是否在
startTime ≤ now ≤ endTime范围内 - 检查剩余库存(
availableCount > 0),注意并发场景下需加锁或用 CAS - 任一条件不满足,立即 new 并 throw
CouponUnavailableException
统一异常处理,避免暴露堆栈
通过 @ControllerAdvice 拦截该异常,转为标准化 JSON 响应:
@ExceptionHandler(CouponUnavailableException.class)
@ResponseBody
public Result<void> handleCouponUnavailable(CouponUnavailableException e) {
return Result.fail("COUPON_UNAVAILABLE", e.getMessage());
}</void>
这样前端可依据 COUPON_UNAVAILABLE 错误码做特定提示(如“该优惠券已过期”或“已被领光”),不显示技术细节。
测试边界场景不可少
单元测试需覆盖典型不可用情形:
- 构造已过期的优惠券,调用领取接口 → 断言抛出
CouponUnavailableException - 设置库存为 0,模拟高并发领取 → 验证最终库存仍为 0,且后续请求均触发异常
- 使用
Mockito模拟 DAO 返回 null 或无效数据,确认校验逻辑提前生效
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










