这是一套 SpringBoot + MyBatis-Plus 实现的优惠券秒杀下单功能,前端用户点击抢购后,后端校验时间、库存,然后扣库存、生成订单并返回结果。
这是一个典型的 Java Spring Boot 后端业务代码 ,实现了优惠券秒杀(Seckill)的核心业务逻辑。我们可以将这段代码拆解为 3 个核心层面来理解:
(1)校验:检查秒杀是否开始、是否结束,以及库存是否足够。
(2)扣减:如果校验通过,减少数据库中的优惠券库存。
(3)创建:在订单表中生成一条订单记录。
(4)返回:告诉用户是否成功,并返回订单 ID。
Controller
@RestController
@RequestMapping("/voucher-order")
public class VoucherOrderController {
@Resource
private IVoucherOrderService voucherOrderService;
@PostMapping("seckill/{id}")
public Result seckillVoucher(@PathVariable("id") Long voucherId) {
return voucherOrderService.seckillVoucher(voucherId);
}
}
Service
public interface IVoucherOrderService extends IService<VoucherOrder> {
Result seckillVoucher(Long voucherId);
}
ServiceImpl
@Service
public class VoucherOrderServiceImpl extends ServiceImpl<VoucherOrderMapper, VoucherOrder> implements IVoucherOrderService {
@Resource
private ISeckillVoucherService seckillVoucherService;
@Resource
private RedisIdWorker redisIdWorker;
@Override
@Transactional
public Result seckillVoucher(Long voucherId) {
// 1.查询优惠券信息
SeckillVoucher voucher = seckillVoucherService.getById(voucherId);
// 2.判断秒杀是否开始
if (voucher.getBeginTime().isAfter(LocalDateTime.now())) {
return Result.fail("秒杀尚未开始!");
}
// 3.判断秒杀是否结束
if (voucher.getEndTime().isBefore(LocalDateTime.now())) {
return Result.fail("秒杀已经结束!");
}
// 4.判断库存是否充足
if (voucher.getStock() < 1) {
return Result.fail("库存不足!");
}
// 5.扣减库存
boolean success = seckillVoucherService.update()
.setSql("stock = stock - 1")
.eq("voucher_id", voucherId)
.update();
if (!success) {
return Result.fail("库存不足!");
}
// 6.创建订单
VoucherOrder voucherOrder = new VoucherOrder();
// 订单ID
long orderId = redisIdWorker.nextId("order");
voucherOrder.setId(orderId);
// 用户ID
Long userId = UserHolder.getUser().getId();
voucherOrder.setUserId(userId);
// 代金券ID
voucherOrder.setVoucherId(voucherId);
save(voucherOrder);
// 7.返回订单号
return Result.ok(orderId);
}
}
整体结构(三层)
-
Controller 层
- 接收前端 HTTP 请求
- 只做转发,不写业务逻辑
- 接口地址:
/voucher-order/seckill/{优惠券ID}
-
Service 接口
- 定义秒杀方法
- 方便解耦、扩展、测试
-
Service 实现类(核心)
- 所有业务逻辑都在这里
- 加了事务
@Transactional,保证扣库存和生成订单要么都成功,要么都失败
整体执行流程(完整逻辑)
- 前端传入优惠券 ID,请求秒杀接口
- 后端根据 ID 查询优惠券信息
- 校验秒杀时间:
- 没开始 → 拒绝
- 已结束 → 拒绝
- 校验库存:
- 库存不足 → 拒绝
- 库存充足 → 执行数据库扣减库存
- 扣减成功 → 生成全局唯一订单 ID
- 创建订单记录(包含用户 ID、优惠券 ID)
- 保存订单到数据库
- 返回订单号给前端,表示秒杀成功
涉及的数据库表
1.tb_seckill_voucher:秒杀优惠券表,存库存、开始结束时间
2.tb_voucher_order:用户秒杀成功后的订单表
关键点总结
1.这是标准后端秒杀业务
2.用了 Spring 事务 保证数据安全
3.用了 Redis 生成唯一订单号
4.用 MyBatis-Plus 简化数据库操作
5.流程:校验时间 → 校验库存 → 扣库存 → 生成订单