秒杀未开始时通过自定义异常seckillnotstartexception配合@controlleradvice统一处理,返回标准json响应;前端同步校验时间并禁用按钮,实现前后端双重风控与友好提示。

在秒杀活动中,未开始时直接拒绝请求是最基础的风控手段。Java 自定义异常配合 Spring 的统一异常处理机制,能清晰、可控地拦截并返回友好提示,避免无效流量冲击系统。
定义秒杀未开始异常
创建一个继承 RuntimeException 的自定义异常类,语义明确、无需强制捕获:
public class SeckillNotStartException extends RuntimeException {
public SeckillNotStartException(String message) {
super(message);
}
}
这样设计便于在业务逻辑中主动抛出,也符合 REST API 中“失败即异常”的常见实践。
在服务层判断并抛出异常
在执行秒杀前(如 seckillService.executeSeckill()),先校验活动时间:
- 从数据库或缓存中查出该秒杀商品的
startTime和endTime - 用
System.currentTimeMillis()对比当前时间 - 若当前时间早于
startTime,直接抛出:throw new SeckillNotStartException("秒杀尚未开始,请稍后再试");
注意:时间比较建议使用毫秒值,避免时区或格式化误差;若用 LocalDateTime,需确保所有环节时区一致(推荐统一用 UTC 或系统默认时区并显式指定)。
全局统一捕获并返回标准响应
用 @ControllerAdvice + @ExceptionHandler 拦截自定义异常,返回前端可识别的 JSON 结构:
@ControllerAdvice
public class SeckillExceptionHandler {
@ExceptionHandler(SeckillNotStartException.class)
@ResponseBody
public ResultVO<void> handleNotStart(SeckillNotStartException e) {
return ResultVO.fail(400, e.getMessage());
}
}
</void>
其中 ResultVO 是你项目中的统一响应封装类(含 code、msg、data 字段)。这样前端收到 { "code": 400, "msg": "秒杀尚未开始..." } 后,可精准提示用户,不跳转、不刷新、不提交。
增强体验:前端同步校验 + 后端兜底
仅靠后端拦截是安全底线,但用户体验更优的方式是前后端双重校验:
- 前端页面加载时,拉取秒杀活动时间,在倒计时组件中实时展示,并禁用按钮直到开始时刻
- 即便用户绕过前端(如手动调接口),后端仍会通过上述自定义异常严格拦截
- 可将活动时间连同商品信息一起返回给前端,避免额外请求
这种组合既减轻服务端压力,又提升用户感知——真正做到了“快有预期,错有反馈”。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











