320-324 秒杀商品完成
完成商品的秒杀
@Controller
public class SeckillController {
@Autowired
private SeckillService seckillService;
@ResponseBody
@GetMapping("/currentSeckillSkus")
public R getCurrentSeckillSkus(){
List 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 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 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);
}
}
}
课件的图