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

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
原文地址:https://www.cnblogs.com/dalianpai/p/13532783.html