(14)SprintBoot 2.X 秒杀地址隐藏

1. 实现思路

1.1 每次点击秒杀按钮,才会生成秒杀地址,秒杀地址不是写死的,是从服务端获取,动态拼接而成的地址。
  • 在进行秒杀之前,去后端获取一个动态的秒杀地址path(服务端生成随机数作为path)将该path存入 redis缓存中,在然后将这个path返回给前端,前端用这个path拼接在新的请求url(url : “/miaosha/” + path + “/do_miaosha”)上作为参数,后端秒杀业务逻辑秒杀前需要判断path与缓存中的path是否一致,一致才进入后续秒杀业务逻辑,否则返回非法请求

2.代码实现

2.1 前端代码
    function getMiaoshaPath(){
        var goodsId = $("#goodsId").val();
        g_showLoading();
        $.ajax({
            url:"/miaosha/path",
            type:"GET",
            data:{
                goodsId:goodsId,
                verifyCode:$("#verifyCode").val()
            },
            success:function(data){
                if(data.code == 0){
                    var path = data.data;
                    doMiaosha(path);
                }else{
                    layer.msg(data.msg);
                }
            },
            error:function(){
                layer.msg("客户端请求有误");
            }
        });
    }
2.2 Controller层获取秒杀地址
    @AccessLimit(seconds=5, maxCount=5, needLogin=true)
    @RequestMapping(value="/path", method=RequestMethod.GET)
    @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);
        }
        String path = miaoshaService.createMiaoshaPath(user,goodsId);
        boolean check = miaoshaService.checkVerifyCode(user, goodsId, verifyCode);
        if(!check) {
            return Result.error(CodeMsg.REQUEST_ILLEGAL);
        }
        return Result.success(path);
    }
2.3 MiaoshaService层
    public String createMiaoshaPath(MiaoshaUser user, long goodsId) {
        if(user == null || goodsId <=0) {
            return null;
        }
        String str = MD5Util.md5(UUIDUtil.uuid()+"123456");
        redisService.set(MiaoshaKey.getMiaoshaPath, ""+user.getId() + "_"+ goodsId, str);
        return str;
    }

    public boolean checkPath(MiaoshaUser user, long goodsId, String path) {
        if(user == null || path == null) {
            return false;
        }
        String pathOld = redisService.get(MiaoshaKey.getMiaoshaPath, ""+user.getId() + "_"+ goodsId, String.class);
        return path.equals(pathOld);
    }
2.4 Controller层 验证path后进行秒杀逻辑业务处理
  • 需要进行path验证,验证通过后才可以进入秒杀业务逻辑,否则返回非法请求
    @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) {

        if(user == null){
            return Result.error(CodeMsg.SESSION_ERROR);//return "login";
        }
        model.addAttribute("user", user);

        //验证path
        boolean check = miaoshaService.checkPath(user, goodsId, path);
        if(!check){
            return Result.error(CodeMsg.REQUEST_ILLEGAL);
        }
        //内存标记,减少redis访问
        boolean isOver = localOverMap.get(goodsId);
        if(isOver){
            return Result.error(CodeMsg.MIAOSHA_OVER);
        }
        //reids预减库存
        long stock = redisService.decr(GoodsKey.getMiaoshaGoodsStock,""+goodsId);
        if(stock < 0){
            localOverMap.put(goodsId,true);
            return Result.error(CodeMsg.MIAOSHA_OVER);
        }
        logger.info("判断是否重复秒杀次数:"+ time++);
        //判断是否重复秒杀到
        MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(),goodsId);
        if(order != null){
            //重复秒杀时需要把预减的库存加回去,并重置localOverMap
            redisService.incr(GoodsKey.getMiaoshaGoodsStock,"" + goodsId);
            localOverMap.put(goodsId,false);
            return Result.error(CodeMsg.REPEATE_MIAOSHA);
        }

        //入队
        MiaoshaMessage message = new MiaoshaMessage();
        message.setUser(user);
        message.setGoodsId(goodsId);
        sender.sendMiaoshaMessage(message);
        return Result.success(0);            //排队中
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值