秒杀代码核心部分

  //内存标记,商品是否卖完
    private HashMap<Long, Boolean> localOverMap =  new HashMap<Long, Boolean>();
    
    /**
     * 系统初始化,加载商品库存,并为每个商品初始化内存标记
     * */
    public void afterPropertiesSet() throws Exception {  //该Controller实现InitializingBean
        List<GoodsVo> goodsList = goodsService.listGoodsVo();
        if(goodsList == null) {
            return;
        }
        for(GoodsVo goods : goodsList) {
            redisService.set(GoodsKey.getMiaoshaGoodsStock, ""+goods.getId(), goods.getStockCount());
            localOverMap.put(goods.getId(), false);
        }
    }
    
    //这里使用pathVariable,为了拼接动态路径,也是一种防刷手段
   @RequestMapping(value
="/{path}/do_miaosha", method=RequestMethod.POST) @ResponseBody public Result<Integer> miaosha(Model model,MiaoshaUser user, @RequestParam("goodsId")long goodsId, @PathVariable("path") String path) { model.addAttribute("user", user); if(user == null) { return Result.error(CodeMsg.SESSION_ERROR); } //验证path boolean check = miaoshaService.checkPath(user, goodsId, path); if(!check){ return Result.error(CodeMsg.REQUEST_ILLEGAL); } //内存标记,减少redis访问,如果没有这一步,也可以,直接去预减库存,但是,会造成redis的负担,所以加一个非线程安全的map,去做一层简单过滤 //同一时间,有可能100个人去抢最后一件商品(get为false),但是没关系,有redis的decr去做原子保障,保证不会超卖 boolean over = localOverMap.get(goodsId); if(over) { return Result.error(CodeMsg.MIAO_SHA_OVER); }
     //开始主流程:预减库存->判断重复秒杀->加入消息队列,返回成功(即排队中)
//预减库存 long stock = redisService.decr(GoodsKey.getMiaoshaGoodsStock, ""+goodsId);//10 if(stock < 0) { localOverMap.put(goodsId, true); redisService.set(GoodsKey.getMiaoshaGoodsStock, ""+goodsId,0); return Result.error(CodeMsg.MIAO_SHA_OVER); } //判断是否已经秒杀到了 //redisService.set(OrderKey.getMiaoshaOrderByUidGid, ""+user.getId()+"_"+goods.getId(), miaoshaOrder); MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId); if(order != null) { redisService.incr(GoodsKey.getMiaoshaGoodsStock, ""+goodsId); localOverMap.put(goodsId, false); return Result.error(CodeMsg.REPEATE_MIAOSHA); } //入队 MiaoshaMessage mm = new MiaoshaMessage(); mm.setUser(user); mm.setGoodsId(goodsId);
     //消息队列发送者,发送消息 sender.sendMiaoshaMessage(mm);
return Result.success(0);//排队中,用户点击秒杀后(内部去请求path,然后用path去请求秒杀服务,然后调轮询接口,查询结果) } /**做延迟任务setTimeOut,轮询秒杀结果 * orderId:成功 * -1:秒杀失败 * 0: 排队中 * */ @RequestMapping(value="/result", method=RequestMethod.GET) @ResponseBody public Result<Long> miaoshaResult(Model model,MiaoshaUser user, @RequestParam("goodsId")long goodsId) { model.addAttribute("user", user); if(user == null) { return Result.error(CodeMsg.SESSION_ERROR); } long result =miaoshaService.getMiaoshaResult(user.getId(), goodsId); return Result.success(result); } @AccessLimit(seconds=5, maxCount=5, needLogin=true)//自定义注解,接口防刷 @RequestMapping(value="/path", method=RequestMethod.GET)//先获取path,才能请求秒杀接口 @ResponseBody public Result<String> getMiaoshaPath(HttpServletRequest request, MiaoshaUser user, @RequestParam("goodsId")long goodsId, @RequestParam(value="verifyCode", defaultValue="0")int verifyCode ) { if(user == null) { return Result.error(CodeMsg.SESSION_ERROR); } boolean check = miaoshaService.checkVerifyCode(user, goodsId, verifyCode); if(!check) { return Result.error(CodeMsg.REQUEST_ILLEGAL); } String path = miaoshaService.createMiaoshaPath(user, goodsId); return Result.success(path); } }

猜你喜欢

转载自www.cnblogs.com/brxHqs/p/9766820.html