引入RabbitMQ秒杀接口异步化

2023-12-24 20:29:35
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("验证码结果错误!");
        }

        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("系统异常,请稍后重试!");
//        }
    }
}

package com.java1234.miaosha.controller;


import com.java1234.miaosha.constant.Constant;
import com.java1234.miaosha.entity.R;
import com.java1234.miaosha.entity.User;
import com.java1234.miaosha.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.imageio.ImageIO;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;


/**
 * 订单控制器
 * @author java1234_小锋
 * @site www.java1234.com
 * @company Java知识分享网
 * @create 2020-12-13 11:20
 */
@Controller
@RequestMapping("/verifyCode")
public class VerifyCodeController {



    @Autowired
    private RedisUtil redisUtil;


    /**
     * 返回验证码图片
     * @param miaoShaGoodsId
     * @return
     */
    @RequestMapping(value = "/get",method = RequestMethod.GET)
    public R get(HttpServletResponse response,String token, Integer miaoShaGoodsId){
        System.out.println("token:"+token);
        System.out.println("miaoShaGoodsId:"+miaoShaGoodsId);
    /*    String token = request.getParameter("token");
        System.out.println("token:"+token);*/
        Object o=redisUtil.get(Constant.REDIS_TOKEN_PREFIX,token);
        if(o==null){
            return null;
        }
        if(miaoShaGoodsId==null || miaoShaGoodsId <=0){
            return null;
        }
        try {
            BufferedImage image = this.createVerifyCodeImage(((User) o).getId(), miaoShaGoodsId);
            ServletOutputStream out = response.getOutputStream();
            ImageIO.write(image,"JPEG",out);
            out.flush();
            out.close();
            return null;
        }catch(Exception e){
            e.printStackTrace();
            return R.error("服务端异常");
        }
    }

    private BufferedImage createVerifyCodeImage(Integer userId,Integer miaoShaGoodsId) {
        int width=80;
        int height=32;
        BufferedImage image=new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
        Graphics g=image.getGraphics();
        g.setColor(new Color(0xDCDCDC));
        g.fillRect(0,0,width,height);
        g.setColor(Color.black);
        g.drawRect(0,0,width-1,height-1);
        Random rdm=new Random();
        for(int i=0;i<50;i++){
            int x=rdm.nextInt(width);
            int y=rdm.nextInt(height);
            g.drawOval(x,y,0,0);
        }

        String verifyCode=createVerifyCode();
        System.out.println("验证:"+verifyCode);
        g.setColor(new Color(0,100,0));
        g.setFont(new Font("Candara",Font.BOLD,24));
        g.drawString(verifyCode+"=",8,24);
        g.dispose();

        int rnd=calc(verifyCode);
        System.out.println("rnd:"+rnd);
        redisUtil.set(Constant.REDIS_VERIFYCODE_PREFIX,userId+","+miaoShaGoodsId,rnd,Constant.REDIS_VERIFYCODE_EXPIRE);

        return image;

    }

    public static void main(String[] args) {
        String verifyCode=createVerifyCode();
        System.out.println(calc(verifyCode));
    }

    /**
     * 计算表达式
     * @param exp
     * @return
     */
    private static int calc(String exp) {
        ScriptEngineManager manager=new ScriptEngineManager();
        ScriptEngine engine = manager.getEngineByName("JavaScript");
        try {
            return (int) engine.eval(exp);
        } catch (ScriptException e) {
            e.printStackTrace();
            return 0;
        }
    }


    private static char[] ops=new char[]{'+','-'};

    /**
     * + - 运算
     * @return
     */
    private static String createVerifyCode() {
        Random rdm=new Random();
        int num1=rdm.nextInt(10);
        int num2=rdm.nextInt(10);
        char op1=ops[rdm.nextInt(2)];
        System.out.println("op1:"+op1);
        String exp=num1+String.valueOf(op1)+num2;
        System.out.println("exp:"+exp);
        return exp;
    }


}

package com.java1234.miaosha.rabbitmq;

import com.java1234.miaosha.config.MQConfig;
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){
            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);








    }

}

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.util;

import com.alibaba.fastjson.JSON;

/**
 * bean string转换工具类
 * @author java1234_小锋
 * @site www.java1234.com
 * @company Java知识分享网
 * @create 2020-12-28 15:10
 */
public class BeanUtil {

    /**
     * 将任意类型转换成字符串
     * @param value
     * @param <T>
     * @return
     */
    public static <T> String beanToString(T value) {
        Class<?> clazz = value.getClass();
        if(clazz == int.class || clazz == Integer.class) {
            return value + "";
        }else if(clazz == String.class) {
            return (String)value;
        }else if(clazz == long.class || clazz == Long.class) {
            return value + "";
        }else {
            return JSON.toJSONString(value);
        }
    }


    /**
     * 把一个字符串转换成bean对象
     * @param str
     * @param <T>
     * @return
     */
    public static <T> T stringToBean(String str, Class<T> clazz) {
        if(str == null || str.length() <= 0 || clazz == null) {
            return null;
        }
        if(clazz == int.class || clazz == Integer.class) {
            return (T)Integer.valueOf(str);
        }else if(clazz == String.class) {
            return (T)str;
        }else if(clazz == long.class || clazz == Long.class) {
            return  (T)Long.valueOf(str);
        }else {
            return JSON.toJavaObject(JSON.parseObject(str), clazz);
        }
    }

}

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