秒杀商品信息放redis中判断

发布时间:2024年01月11日
methods: {
    getSrcUrl(t) {
      return getServerUrl('image/' + t);
    },
    exec_miaosha(){
      if(this.verifyCode==""){
        alert("请输入验证码结果!");
        return;
      }
      let url = getServerUrl("miaoSha/exec");
      let token = window.sessionStorage.getItem("token");
      axios.defaults.headers.common['token'] = token;
      axios.get(url,{
        params:{
          miaoShaGoodsId:this.$route.params.id,
          verifyCode:this.verifyCode
        }
      }).then(response=>{
         let data = response.data;
        this.miaoShaGoods.miaoShaStatus=4;
         if(data.code!=0){
           alert(data.msg);
           this.miaoShaResult=data.msg;
         }else{
           // alert(data.orderId);

           this.miaoShaResult=data.msg;
           this.getMiaoShaResult(this.$route.params.id);
         }
      }).catch(error=>{
        alert(error+"-请联系管理员");
      })
    },
    getMiaoShaResult(miaoShaGoodsId){
      let url = getServerUrl("miaoSha/result");
      let token = window.sessionStorage.getItem("token");
      axios.defaults.headers.common['token'] = token;
      axios.get(url,{
        params:{
          miaoShaGoodsId:this.$route.params.id
        }
      }).then(response=>{
        let data = response.data;
        if(data.code!=0){
          alert(data.msg);
          this.miaoShaResult=data.msg;
        }else{
          let result=data.result;
          if(result=="0"){  // 排队中,继续轮询
              setTimeout(function (){
                  this.getMiaoShaResult(miaoShaGoodsId)
              },50);
          }else if(result=="-1"){
              this.miaoShaResult="秒杀失败";
          }else{
            alert("秒杀成功! ");
            alert(result);
          }
        }
      }).catch(error=>{
        alert(error+"-请联系管理员");
      })
    },
package com.java1234.miaosha.service.impl;

import com.java1234.miaosha.constant.Constant;
import com.java1234.miaosha.entity.Order;
import com.java1234.miaosha.entity.User;
import com.java1234.miaosha.mapper.MiaoShaGoodsMapper;
import com.java1234.miaosha.mapper.OrderMapper;
import com.java1234.miaosha.service.IMiaoShaService;
import com.java1234.miaosha.util.DateUtil;
import com.java1234.miaosha.util.RedisUtil;
import com.java1234.miaosha.vo.MiaoShaGoodsVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;

/**
 * 秒杀Service实现类
 */
@Service("miaoShaService")
public class MiaoShaServiceImpl implements IMiaoShaService {


    @Autowired
    private MiaoShaGoodsMapper miaoShaGoodsMapper;

    @Autowired
    private OrderMapper orderMapper;


    @Autowired
    private RedisUtil redisUtil;
    /**
     * 如果执行成功,返回订单ID,否则返回Null
     * @param user
     * @param miaoShaGoodsVo
     * @return
     */
    @Override
    @Transactional
    public String miaoSha(User user, MiaoShaGoodsVo miaoShaGoodsVo) {
        //库存减1操作
        Integer affectedRows = miaoShaGoodsMapper.reduceStock(miaoShaGoodsVo.getId());

        if(affectedRows==0){
            return null;
        }

        //生成订单
        Order order = new Order();
        order.setId(DateUtil.getCurrentDateStr());  //生成订单号
        order.setUser(user);
        order.setMiaoShaGoods(miaoShaGoodsVo);
        order.setCount(1);
        order.setTotalPrice(miaoShaGoodsVo.getPrice());
        order.setPayMethod(null);
        order.setStatus(0);
        Integer affectedRows2 = orderMapper.add(order);
        if(affectedRows2==0){
            return null;
        }
        return order.getId();
    }

    @Override
    public String getMiaoShaResult(Integer userId, Integer miaoShaGoodsId) {
        HashMap map=new HashMap();
        map.put("user_id",userId);
        map.put("miaosha_goods_id",miaoShaGoodsId);
        Order order=orderMapper.findByUserIdAndMiaoShaGoodsId(map);
        if(order!=null){
            return order.getId();
        }else{
            //  TODO 查询商品是否秒杀完 从redis中判断是否商品秒杀完
            boolean isOver = (boolean) redisUtil.get(Constant.REDIS_GOODS_MIAOSHA_OVER_PREFIX, miaoShaGoodsId + "");

            boolean over=true;
            if(over){
                return "-1";
            }else{
                return "0";
            }
        }
    }
}

package com.java1234.miaosha.controller;

import com.java1234.miaosha.constant.Constant;
import com.java1234.miaosha.entity.MiaoShaMessage;
import com.java1234.miaosha.entity.Order;
import com.java1234.miaosha.entity.R;
import com.java1234.miaosha.entity.User;
import com.java1234.miaosha.rabbitmq.MQSender;
import com.java1234.miaosha.service.IMiaoShaGoodsService;
import com.java1234.miaosha.service.IMiaoShaService;
import com.java1234.miaosha.service.IOrderService;
import com.java1234.miaosha.util.RedisUtil;
import com.java1234.miaosha.util.StringUtil;
import com.java1234.miaosha.vo.MiaoShaGoodsVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * 秒杀控制器
 */
@RestController
@RequestMapping("/miaoSha")
public class MiaoShaController {

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private IMiaoShaGoodsService miaoShaGoodsService;

    @Autowired
    private IMiaoShaService miaoShaService;

    @Autowired
    private IOrderService orderService;


    @Autowired
    private MQSender mqSender;

    /**
     * 执行秒杀
     * @param request
     * @param miaoShaGoodsId
     * @return
     */
    @RequestMapping("/exec")
    public R exec(HttpServletRequest request, Integer miaoShaGoodsId,String verifyCode){
        if(StringUtil.isEmpty(verifyCode)){
            return R.error("验证码不能为空!");
        }
        //第一步:根据token得到用户user对象
        String token = request.getHeader("token");
        System.out.println("token:"+token);
        User user = (User)redisUtil.get(Constant.REDIS_TOKEN_PREFIX, token);
        System.out.println(user);

        Object rnd=redisUtil.get(Constant.REDIS_VERIFYCODE_PREFIX, user.getId() + "," + miaoShaGoodsId);
        if(rnd==null){
            return R.error("验证码过期,请重新点击刷新验证码!");
        }
        if(!verifyCode.equals(String.valueOf(rnd))){
            return R.error("验证码结果错误!");
        }

        boolean isOver = (boolean) redisUtil.get(Constant.REDIS_GOODS_MIAOSHA_OVER_PREFIX, miaoShaGoodsId + "");
        if(isOver){
            return R.ok("秒杀结束");
        }
        long stock = redisUtil.decr(Constant.REDIS_STOCK_PREFIX, miaoShaGoodsId + "", 1);
        if(stock<0){
            return R.error("秒杀失败,商品已经秒光,欢迎参与!");
        }
        MiaoShaMessage mm=new MiaoShaMessage();
        mm.setUser(user);
        mm.setMiaoShaGoodsId(miaoShaGoodsId);
        mqSender.sendMiaoShaMessage(mm);

        return R.ok("排队中");
//        //第二步:判断库存是否足够
//        MiaoShaGoodsVo miaoShaGoods = miaoShaGoodsService.findById(miaoShaGoodsId);
//        Integer stock = miaoShaGoods.getStock();
//        if(stock<=0){
//            return R.error("库存不足!");
//        }
//
//        //第三步:判断用户是否重复秒杀
//        HashMap map = new HashMap();
//        map.put("user_id",user.getId());
//        map.put("miaosha_goods_id",miaoShaGoodsId);
//        Order orderE = orderService.findByUserIdAndMiaoShaGoodsId(map);
//        if(orderE!=null){
//            return R.error("您已经秒杀过此商品,不能重复秒杀");
//        }
//
//        //第四步:减库存,下订单,必须同一个事务
//        String orderId = miaoShaService.miaoSha(user, miaoShaGoods);
//        if(orderId!=null){
//            Map<String,Object> resultMap=new HashMap<>();
//            resultMap.put("orderId",orderId);
//            return R.ok(resultMap);
//        }else{
//            return R.error("系统异常,请稍后重试!");
//        }
    }

    /**
     * 秒杀结果查询
     * @param request
     * @param miaoShaGoodsId
     * @return  >0 返回orderId 订单ID -1 秒杀失败 0  排队中
     */
    @RequestMapping("/result")
    public R result(HttpServletRequest request,Integer miaoShaGoodsId){
        String token = request.getHeader("token");
        System.out.println("token:"+token);
        User user = (User)redisUtil.get(Constant.REDIS_TOKEN_PREFIX, token);
        System.out.println(user);
        String result=miaoShaService.getMiaoShaResult(user.getId(),miaoShaGoodsId);
        Map<String,Object> resultMap=new HashMap<>();
        resultMap.put("result",result);
        return R.ok(resultMap);
    }
}

package com.java1234.miaosha.rabbitmq;


import com.java1234.miaosha.config.MQConfig;
import com.java1234.miaosha.entity.MiaoShaMessage;
import com.java1234.miaosha.util.BeanUtil;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class MQSender {

    @Autowired
    private AmqpTemplate amqpTemplate;

    public void sendMiaoShaMessage(MiaoShaMessage miaoShaMessage){
        String msg = BeanUtil.beanToString(miaoShaMessage);
        System.out.println("send message:"+msg);
        amqpTemplate.convertAndSend(MQConfig.MIAOSHA_QUEUE,msg);
    }
}

package com.java1234.miaosha.run;

import com.java1234.miaosha.constant.Constant;
import com.java1234.miaosha.service.IMiaoShaGoodsService;
import com.java1234.miaosha.util.RedisUtil;
import com.java1234.miaosha.vo.MiaoShaGoodsVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * 启动的时候加载加载秒杀商品库存信息和是否秒杀完成标识
 */
@Component("startupRunner")
public class StartupRunner implements CommandLineRunner {

    @Autowired
    private IMiaoShaGoodsService miaoShaGoodsService;

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public void run(String... args) throws Exception {
        List<MiaoShaGoodsVo> miaoShaGoodsVoList = miaoShaGoodsService.listAll();
        System.out.println("启动加载秒杀库存信息");
        for(MiaoShaGoodsVo miaoShaGoodsVo:miaoShaGoodsVoList){
            System.out.println(miaoShaGoodsVo.getId()+":"+miaoShaGoodsVo.getStock());
            redisUtil.set2(Constant.REDIS_STOCK_PREFIX,miaoShaGoodsVo.getId()+"",miaoShaGoodsVo.getStock()+"");
            redisUtil.set(Constant.REDIS_GOODS_MIAOSHA_OVER_PREFIX,miaoShaGoodsVo.getId()+"",false);
        }
    }
}

package com.java1234.miaosha.rabbitmq;

import com.java1234.miaosha.config.MQConfig;
import com.java1234.miaosha.constant.Constant;
import com.java1234.miaosha.entity.MiaoShaMessage;
import com.java1234.miaosha.entity.Order;
import com.java1234.miaosha.entity.R;
import com.java1234.miaosha.entity.User;
import com.java1234.miaosha.service.IMiaoShaGoodsService;
import com.java1234.miaosha.service.IMiaoShaService;
import com.java1234.miaosha.service.IOrderService;
import com.java1234.miaosha.util.BeanUtil;
import com.java1234.miaosha.util.RedisUtil;
import com.java1234.miaosha.vo.MiaoShaGoodsVo;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;


@Service
public class MQReceiver {

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private IMiaoShaGoodsService miaoShaGoodsService;

    @Autowired
    private IMiaoShaService miaoShaService;

    @Autowired
    private IOrderService orderService;




    @RabbitListener(queues = MQConfig.MIAOSHA_QUEUE)
    public void receiveMiaoShaMessage(String message){
        MiaoShaMessage miaoShaMessage = BeanUtil.stringToBean(message, MiaoShaMessage.class);
        System.out.println("receive message:"+miaoShaMessage);
        User user = miaoShaMessage.getUser();

        Integer miaoShaGoodsId=miaoShaMessage.getMiaoShaGoodsId();

        //第二步:判断库存是否足够
        MiaoShaGoodsVo miaoShaGoods = miaoShaGoodsService.findById(miaoShaGoodsId);
        Integer stock = miaoShaGoods.getStock();
        if(stock<=0){
            redisUtil.set(Constant.REDIS_GOODS_MIAOSHA_OVER_PREFIX,miaoShaGoodsId+"",true);
            System.out.println("库存不足");
            return;
        }
        //第三步:判断用户是否重复秒杀
        HashMap map = new HashMap();
        map.put("user_id",user.getId());
        map.put("miaosha_goods_id",miaoShaGoodsId);
        Order orderE = orderService.findByUserIdAndMiaoShaGoodsId(map);
        if(orderE!=null){
              System.out.println("您已经秒杀过此商品,不能重复秒杀");
              return;
        }

        //第四步:减库存,下订单,必须同一个事务
        String orderId = miaoShaService.miaoSha(user, miaoShaGoods);








    }

}

server:
  port: 80
  servlet:
    context-path: /

spring:
  rabbitmq:
    host: 192.168.30.113
    port: 5672
    username: admin
    password: admin
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db_miaosha3?serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  redis: # redis配置
    host: 192.168.30.113 # IP
    port: 6379  # 端口
    password:  # 密码
    connect-timeout: 10s  # 连接超时时间
    lettuce: # lettuce redis客户端配置
      pool: # 连接池配置
        max-active: 8  # 连接池最大连接数(使用负值表示没有限制) 默认 8
        max-wait: 200s  # 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
        max-idle: 8 # 连接池中的最大空闲连接 默认 8
        min-idle: 0 # 连接池中的最小空闲连接 默认 0

mybatis-plus:
  configuration:
    map-underscore-to-camel-case: true  # 开启驼峰功能  userName  - >  user_name
    auto-mapping-behavior: full  # 自动mapping映射
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  mapper-locations: classpath:mybatis/mapper/*.xml


文章来源:https://blog.csdn.net/m0_68935893/article/details/135520171
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。