• 谷粒商城秒杀商品完成(四十七)


    320-324 秒杀商品完成

    完成商品的秒杀

    @Controller
    public class SeckillController {
    
        @Autowired
        private SeckillService seckillService;
    
        @ResponseBody
        @GetMapping("/currentSeckillSkus")
        public R getCurrentSeckillSkus(){
            List<SecKillSkuRedisTo> vos = seckillService.getCurrentSeckillSkus();
            return R.ok().setData(vos);
        }
    
        @ResponseBody
        @GetMapping("/sku/seckill/{skuId}")
        public R getSkuSeckillInfo(@PathVariable("skuId") Long skuId){
            SecKillSkuRedisTo to = seckillService.getSkuSeckillInfo(skuId);
            return R.ok().setData(to);
        }
    
        @GetMapping("/kill")
        public String secKill(@RequestParam("killId") String killId, @RequestParam("key") String key, @RequestParam("num") Integer num, Model model){
            String orderSn = seckillService.kill(killId,key,num);
            System.out.println(orderSn);
            // 1.判断是否登录
            model.addAttribute("orderSn", orderSn);
            return "success";
        }
    }
    
    

    拦截器:配置的时候看了一下手机,结果放行有问题,查看商品详情的时候一直有问题,找了2个小时,最后终于找到了

    /**
     * @author WGR
     * @create 2020/7/27 -- 21:52
     */
    @Component
    public class LoginUserInterceptor implements HandlerInterceptor {
    
        public static ThreadLocal<MemberRespVo> loginUser = new ThreadLocal<>();
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            String uri = request.getRequestURI();
            boolean match = new AntPathMatcher().match("/kill", uri);
            if(match ){
                MemberRespVo attribute = (MemberRespVo)request.getSession().getAttribute(AuthServerConstant.LOGIN_USER);
                if(attribute !=null){
                    loginUser.set(attribute);
                    return true;
                }else{
                    request.getSession().setAttribute("msg","请先进行登录");
                    response.sendRedirect("http://auth.gulimall.com/login.html");
                    return false;
                }
            }
    
            return true;
    
        }
    }
    
    

    秒杀的方法

      @Override
        public String kill(String killId, String key, Integer num) {
            MemberRespVo memberRsepVo = LoginUserInterceptor.loginUser.get();
    
            // 1.获取当前秒杀商品的详细信息
            BoundHashOperations<String, String, String> hashOps = redisTemplate.boundHashOps(SKUKILL_CACHE_PREDIX);
            String json = hashOps.get(killId);
            System.out.println(killId);
            System.out.println(json);
            if(StringUtils.isEmpty(json)){
                return null;
            }else{
                SecKillSkuRedisTo redisTo = JSON.parseObject(json, SecKillSkuRedisTo.class);
                // 校验合法性
                long time = new Date().getTime();
                if(time >= redisTo.getStartTime() && time <= redisTo.getEndTime()){
                    // 1.校验随机码跟商品id是否匹配
                    String randomCode = redisTo.getRandomCode();
                    String skuId = redisTo.getPromotionSessionId() + "_" + redisTo.getSkuId();
    
                    if(randomCode.equals(key) && killId.equals(skuId)){
                        // 2.说明数据合法
                        Integer limit = redisTo.getSeckillLimit();
                        if(num <= limit){
                            // 3.验证这个人是否已经购买过了
                            String redisKey = memberRsepVo.getId() + "_" + skuId;
                            // 让数据自动过期
                            long ttl = redisTo.getEndTime() - redisTo.getStartTime();
    
                            Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent(redisKey, num.toString(), ttl<0?0:ttl, TimeUnit.MILLISECONDS);
                            if(aBoolean){
                                // 占位成功 说明从来没买过
                                RSemaphore semaphore = redissonClient.getSemaphore(SKU_STOCK_SEMPHORE + randomCode);
    
                                boolean  acquire = semaphore.tryAcquire(num);
                                if(acquire){
                                    // 秒杀成功
                                    // 快速下单 发送MQ
                                    String orderSn = IdWorker.getTimeId() + UUID.randomUUID().toString().replace("-","").substring(7,8);
                                    SecKillOrderTo orderTo = new SecKillOrderTo();
                                    orderTo.setOrderSn(orderSn);
                                    orderTo.setMemberId(memberRsepVo.getId());
                                    orderTo.setNum(num);
                                    orderTo.setSkuId(redisTo.getSkuId());
                                    orderTo.setSeckillPrice(redisTo.getSeckillPrice());
                                    orderTo.setPromotionSessionId(redisTo.getPromotionSessionId());
                                    rabbitTemplate.convertAndSend("order-event-exchange","order.seckill.order", orderTo);
                                    return orderSn;
                                }
                            }else {
                                return null;
                            }
                        }
                    }else{
                        return null;
                    }
                }else{
                    return null;
                }
            }
            return null;
    }
    

    订单服务的监听类

    /**
     * @author WGR
     * @create 2020/8/19 -- 22:54
     */
    @RabbitListener(queues = "order.seckill.order.queue")
    @Component
    public class OrderSecKillListener {
    
        @Autowired
        private OrderService orderService;
    
        @RabbitHandler
        public void listener(SecKillOrderTo secKillOrderTo, Channel channel, Message message) throws IOException {
            try {
                // 创建秒杀单的信息
                orderService.createSecKillOrder(secKillOrderTo);
                channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
            } catch (Exception e) {
                channel.basicReject(message.getMessageProperties().getDeliveryTag(),true);
            }
        }
    }
    

    课件的图

    image-20200819221041677 image-20200819221110653 image-20200819221131327 image-20200819221027920 image-20200819224042349
  • 相关阅读:
    C++编译器详解(二)常见precompiling 指令介绍
    C++编译器详解(一)
    Music
    jQuery语法
    Freedom DownTime
    A
    Map类
    伤不起:File.toPath() & Paths.get()
    在不同浏览器中空格显示的效果不一致的问题(主要是宽度不一致)
    关于xmlhttp会使用ie的缓存的问题及解决
  • 原文地址:https://www.cnblogs.com/dalianpai/p/13532783.html
Copyright © 2020-2023  润新知