zoukankan      html  css  js  c++  java
  • 商品和订单中使用MQ

    一、将Product服务增加到配置中心

    1、添加引用

    <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-config-client</artifactId>
            </dependency>
    

      

    2、修改application.yml 为bootstrap.yml

    eureka:
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka/
    spring:
      application:
        name: product
      cloud:
          config:
            discovery:
              enabled: true
              service-id: CONFIG
            profile: dev
    

      

    3、在码云中添加product-dev.yml文件

    spring:
      datasource:
        driver-class-name: com.mysql.jdbc.Driver
        username: root
        password: 123456
        url: jdbc:mysql://127.0.0.1:3306/SpringCloud_Sell?characterEncoding=utf-8&useSSL=false
      jpa:
        show-sql: true
    

      

    4、访问http://localhost:8080/product-dev.yml

     5、启动Product服务

    二、添加消息队列到Product服务

    1、添加引用

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-amqp</artifactId>
            </dependency>
    

      

    2、添加MQ配置

    3、在扣库存的地方发送消息

     1)发送MQ消息

    @Service
    public class ProductServiceImpl  implements ProductService{
    
        @Autowired
        private ProductInfoRepository productInfoRepository;
    
        @Autowired
        private AmqpTemplate amqpTemplate;
    
     
        /**
         * 扣库存
         *
         * @param cartDTOList
         */
        @Override
        @Transactional  //由于扣库存是list操作,所以需要事务操作
        public void decreaseStock(List<CartDTO> cartDTOList) {
            for(CartDTO cartDTO : cartDTOList){
               Optional<ProductInfo> productInfoOptional =  productInfoRepository.findById(cartDTO.getProductId());
               //判断商品是否存在
               if(!productInfoOptional.isPresent()){
                    throw new ProductException(ResultEnum.PRODUCT_NOT_EXIST);
               }
               ProductInfo productInfo = productInfoOptional.get();
               //库存是否足够  数据库里的库存-购物车中的数量
              Integer result = productInfo.getProductStock() - cartDTO.getProductQuantity();
              if(result <= 0){
                    throw new ProductException(ResultEnum.PRODUCT_STOCK_ERROR);
              }
              productInfo.setProductStock(result);
              productInfoRepository.save(productInfo);
    
              // 发送MQ消息
                amqpTemplate.convertAndSend("productInfo", JsonUtil.toJson(productInfo));
            }
        }
    }
    

      

    之后将发送的对象改为ProductInfoOutput

             ProductInfoOutput output = new ProductInfoOutput();
              BeanUtils.copyProperties(productInfo,output);
              // 发送MQ消息
                amqpTemplate.convertAndSend("productInfo", JsonUtil.toJson(output));
    

      

    2)建立prouductInfo队列,并观察

    3、调用接口

        @PostMapping("/decreaseStock")
        public void decreaseStock(@RequestBody List<CartDTO> cartDTOList){
              productService.decreaseStock(cartDTOList);
        }
    

      

    使用PostMan调用

    最终测试结果,发现2)中的消息队列有了消息。然后查看消息的内容

    三、在Order服务中接收消息

    @Component
    @Slf4j
    public class ProductInfoReceiver {
        @RabbitListener(queuesToDeclare = @Queue("productInfo"))
        public void process(String message){
           //message 转换成 ProductInfoOutpur
           ProductInfoOutput output = (ProductInfoOutput) JsonUtil.fromJson(message,ProductInfoOutput.class);
            log.info("从队列[{}]接收到消息:{}","productInfo", output.toString());
        }
    }
    

      接收到的结果为:

    四、Order服务中将库存保存到Redis中

    1)增加引用

            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
    

      

    2)增加配置

    3)增加代码

    4)调用减库存后,查看Reids的库存数据如下图

    五、优化扣库存

    1、Product服务扣库存

        @Override
        public void decreaseStock(List<CartDTO> cartDTOList) {
            List<ProductInfo> productInfoList = decreaseStockProcess(cartDTOList);
           List<ProductInfoOutput> productInfoOutputList =  productInfoList.stream().map(e -> {
                ProductInfoOutput output = new ProductInfoOutput();
                BeanUtils.copyProperties(e,output);
                return  output;
            }).collect(Collectors.toList());
            // 发送MQ消息
            amqpTemplate.convertAndSend("productInfo", JsonUtil.toJson(productInfoOutputList));
        }
    
    
        @Transactional  //由于扣库存是list操作,所以需要事务操作
        public List<ProductInfo> decreaseStockProcess(List<CartDTO> cartDTOList) {
            List<ProductInfo> productInfoList = new ArrayList<>();
            for(CartDTO cartDTO : cartDTOList){
                Optional<ProductInfo> productInfoOptional =  productInfoRepository.findById(cartDTO.getProductId());
                //判断商品是否存在
                if(!productInfoOptional.isPresent()){
                    throw new ProductException(ResultEnum.PRODUCT_NOT_EXIST);
                }
                ProductInfo productInfo = productInfoOptional.get();
                //库存是否足够  数据库里的库存-购物车中的数量
                Integer result = productInfo.getProductStock() - cartDTO.getProductQuantity();
                if(result <= 0){
                    throw new ProductException(ResultEnum.PRODUCT_STOCK_ERROR);
                }
                productInfo.setProductStock(result);
                productInfoRepository.save(productInfo);
    
               productInfoList.add(productInfo);
    
            }
            return  productInfoList;
        }
    

      

    2)、订单服务接收mq消息

    public class ProductInfoReceiver {
    
        private static final String PRODUCT_STOCK_TEMPLATE = "product_stock_%s";
    
        @Autowired
        private StringRedisTemplate stringRedisTemplate;
    
        @RabbitListener(queuesToDeclare = @Queue("productInfo"))
        public void process(String message){
           //message 转换成 ProductInfoOutpur
           List<ProductInfoOutput> productInfoOutputList = ( List<ProductInfoOutput>) JsonUtil.fromJson(message,
                   new TypeReference<List<ProductInfoOutput>>() {});
            log.info("从队列[{}]接收到消息:{}","productInfo", productInfoOutputList);
            //将消息存到redis
            for (ProductInfoOutput productInfoOutput : productInfoOutputList) {
                stringRedisTemplate.opsForValue().set(String.format(PRODUCT_STOCK_TEMPLATE,
                        productInfoOutput.getProductId()), productInfoOutput.getProductStock().toString());
            }
    
    
        }
    }
    

      

  • 相关阅读:
    js 原生ajax实现
    layer 查看图片
    c# 操作XML
    C# 扩展方法
    c# 依赖注入
    visual studio 快捷键
    HIS系统结算后,没有更新单据状态为“已结算”
    网络流四·最小路径覆盖 HihoCoder
    飞行员配对(二分图最大匹配) 51Nod
    开心的小Q 51Nod
  • 原文地址:https://www.cnblogs.com/linlf03/p/10375895.html
Copyright © 2011-2022 走看看