介绍

秒杀活动是吸引用户参与并增加流量的一个重要手段,由于秒杀活动的高并发和竞争激烈,如何确保秒杀活动的公平、公正和系统的稳定性。如何通过一人一单、防止黄牛和秒杀限购来构建一个高效的商城秒杀系统。

每个用户在秒杀活动中只能购买一件商品,防止某些用户通过恶意手段(如脚本)刷单。

一人一单
在这里插入图片描述

依赖

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
</dependency>

用于 Aspect-Oriented Programming (AOP) 的实现。允许你通过切面(aspects)来增强 Java 程序的功能,比如日志、事务、权限检查等。

库存查询

@Override
@SneakyThrows
/**
 * 秒杀商品
 */
public boolean secKillGood(int goodId)   {


    Goods goods =goodsMapper.selectById(goodId);

    if(goods.getStock()<1){ //查询商品库存
        return false; //没有库存
    }
    Integer userId=1;
    //先获取锁在去完成下单的操作
    synchronized (userId.toString().intern()){ //方法加锁
        IGoodsService proxy =(IGoodsService) AopContext.currentProxy();
        return proxy.createOrder(goodId,userId);
    }
    
    }
  • userId.toString().intern():这里对 userId(假设它是一个对象)的 toString() 方法结果调用 intern() 方法,目的是将该字符串的引用指向常量池中的唯一引用。intern() 方法确保同样的字符串只有一个实例,避免创建多个相同内容的对象,从而保证锁的唯一性。

创建订单

@Override
@Transactional
/**
 * 生成订单
 */
public boolean createOrder(int goodId, int userId){

    //查询是否已经购买过
    LambdaUpdateWrapper<Order> orderLambdaUpdateWrapper =new LambdaUpdateWrapper<>();
    orderLambdaUpdateWrapper.eq(Order::getUserId,userId) //用户ID
            .eq(Order::getGoodId,goodId); //商品ID
    Long count =orderMapper.selectCount(orderLambdaUpdateWrapper);//查询是否已经购买过

    if(count>0){ //已经购买过
        return false;
    }

    //扣减库存
    LambdaUpdateWrapper<Goods> goodsLambdaQueryWrapper =new LambdaUpdateWrapper<>();
    goodsLambdaQueryWrapper.eq(Goods::getId,goodId).setSql("stock = stock-1") //扣减库存
            .gt(Goods::getStock,0); //扣减时库存大于1 还有库存


    //扣减库存成功 生成订单
    if( goodsMapper.update(null,goodsLambdaQueryWrapper)>0){
        //生成订单
        Order order= new Order();
        order.setGoodId(goodId);//购买的商品ID
        order.setOrderId(UUID.randomUUID()+""); //生成订单编号
        order.setUserId(userId);//购买的用户
        return orderMapper.insert(order)>0;
    }
    return false;
}

暴露代理

@SpringBootApplication
@EnableAspectJAutoProxy(exposeProxy = true)
public class GoodsApplication {
    public static void main(String[] args) {
        SpringApplication.run(GoodsApplication.class, args);
    }
}

启用 Spring AOP 的自动代理功能,允许通过 AOP 来拦截和增强方法的执行。自动配置 Spring 应用上下文中的 AOP 代理,支持基于 AspectJ 的 AOP,简化了对切面(Aspect)和增强(Advice)的配置。

一人一单
在这里插入图片描述

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐