十四、SpringCloud之在商品和订单服务中使用MQ、Redis - Go语言中文社区

十四、SpringCloud之在商品和订单服务中使用MQ、Redis


一、商品服务

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <!-- 父项目 -->
    <parent>
        <groupId>com.imooc</groupId>
        <artifactId>product</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <artifactId>product-server</artifactId>
    <name>server</name>
    <description>Demo project for Spring Boot</description>

    <!-- 引入依赖 -->
    <dependencies>
        <!-- 引入web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 引入eureka-client -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 引入data-jpa -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <!-- 引入mysql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- 引入lombok 可以省去get set方法 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!-- 引入amqp -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
        <!-- 引入bus-amqp 消息队列-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>
        <!-- 引入config-client 配置中心-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-client</artifactId>
        </dependency>
        <!-- 引入Spring Cloud Stream -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- 引入product-common-->
        <dependency>
            <groupId>com.imooc</groupId>
            <artifactId>product-common</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
        <!-- 引入jackson-annotations -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>2.9.0</version>
        </dependency>

    </dependencies>
    <!--打包-->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

bootstrap.yml

spring:
  application:
    name: product #配置服务名称
  #统一配置中心
  cloud:
      config:
        discovery:
          enabled: true
          service-id: CONFIG   #configServer 服务的名字
        profile: test
      bus:
        trace:
          enabled: true
      stream:
        bindings:
          input: #消息名字
            group: order #消息分组  项目不管启动多少实例,都只有一个实例接收消息
            content-type: application/json #序列化

product-test.yml(统一配置中心)

spring:
  application:
    #配置服务名称
    name: product 
  #配置数据源
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/SpringCloud_Sell?characterEncoding=utf-8&useSSL=false
  jpa:
    show-sql: true
    #消息队列
  rabbitmq:
    host: 192.168.3.233
    username: guest
    password: guest
    port: 5672
# 配置Eureka
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
#配置端扣号
server:
port: 8804

JsonUtil

package com.imooc.product.utils;


import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class JsonUtil {
	private static ObjectMapper objectMapper = new ObjectMapper();
	//转换为json字符串
	public static String toJson(Object object) {
		try {
			return objectMapper.writeValueAsString(object);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}
		return null;
	}
}

ProductServiceImpl

package com.imooc.product.service.impl;

import com.imooc.product.common.DecreaseStockInput;
import com.imooc.product.common.ProductInfoOutput;
import com.imooc.product.dataobject.ProductInfo;
import com.imooc.product.enums.ProductStatusEnum;
import com.imooc.product.enums.ResultEnum;
import com.imooc.product.exception.ProductException;
import com.imooc.product.repository.ProductInfoRepository;
import com.imooc.product.service.ProductService;
import com.imooc.product.utils.JsonUtil;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

//商品
@Service
public class ProductServiceImpl implements ProductService {
    //引入商品Dao
    @Autowired
    private ProductInfoRepository productInfoRepository;

    //引入消息
    @Autowired
    private AmqpTemplate amqpTemplate;

    //查询所有在架商品列表
    @Override
    public List<ProductInfo> findUpAll() {
        return productInfoRepository.findByProductStatus(ProductStatusEnum.UP.getCode());
    }

    //根据productIdList查询商品列表
    @Override
    public List<ProductInfoOutput> findList(List<String> productIdList) {
        return productInfoRepository.findByProductIdIn(productIdList).stream()
                .map(e -> {
                    ProductInfoOutput output = new ProductInfoOutput();
                    BeanUtils.copyProperties(e, output);
                    return output;
                })
                .collect(Collectors.toList());
    }

    /**
     * 扣库存并发送消息
     * */
    @Override
    public void decreaseStock(List<DecreaseStockInput> decreaseStockInputList) {
        //扣库存逻辑
        List<ProductInfo> productInfoList = decreaseStockProcess(decreaseStockInputList);
        //把ProductInfo转换为ProductInfoOutput
        List<ProductInfoOutput> productInfoOutputList = productInfoList.stream().map(e -> {
            ProductInfoOutput output = new ProductInfoOutput();
            BeanUtils.copyProperties(e, output);//将e的属性值复制给output
            return output;
        }).collect(Collectors.toList());
        //发送mq消息
        amqpTemplate.convertAndSend("productInfo", JsonUtil.toJson(productInfoOutputList));
    }

    /**
     * 扣库存逻辑
     * */
    @Transactional
    public List<ProductInfo> decreaseStockProcess(List<DecreaseStockInput> decreaseStockInputList) {
        List<ProductInfo> productInfoList = new ArrayList<>();
        for (DecreaseStockInput decreaseStockInput: decreaseStockInputList) {
            Optional<ProductInfo> productInfoOptional = productInfoRepository.findById(decreaseStockInput.getProductId());
            //判断商品是否存在
            if (!productInfoOptional.isPresent()){
                throw new ProductException(ResultEnum.PRODUCT_NOT_EXIST);
            }

            ProductInfo productInfo = productInfoOptional.get();
            //库存是否足够
            Integer result = productInfo.getProductStock() - decreaseStockInput.getProductQuantity();
            if (result < 0) {
                throw new ProductException(ResultEnum.PRODUCT_STOCK_ERROR);
            }

            productInfo.setProductStock(result);
            productInfoRepository.save(productInfo);
            productInfoList.add(productInfo);
        }
        return productInfoList;
    }
}

二、订单服务

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!-- 父项目 -->
    <parent>
        <artifactId>order</artifactId>
        <groupId>com.imooc</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <artifactId>order-server</artifactId>
    <!-- 引入依赖 -->
    <dependencies>
        <!-- 引入web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!-- 引入eureka-client -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- 引入data-jpa -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <!-- 引入mysql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!-- 引入lombok 可以省去get set方法 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!-- 引入gson 转换数据-->
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
        </dependency>
        <!-- 引入feign 应用通信-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-feign</artifactId>
            <version>1.4.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- 引入order-common-->
        <dependency>
            <groupId>com.imooc</groupId>
            <artifactId>order-common</artifactId>
        </dependency>
        <!-- 引入product-client -->
        <dependency>
            <groupId>com.imooc</groupId>
            <artifactId>product-client</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <scope>compile</scope>
        </dependency>
        <!-- 引入cloud-config-client 统一配置中心 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-client</artifactId>
        </dependency>
        <!-- 引入bus-amqp 消息队列-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bus-amqp</artifactId>
        </dependency>
        <!-- 引入Spring Cloud Stream -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <!-- 引入redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
    </dependencies>
    <!-- 版本依赖管理 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <!-- 打包 -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
    <!-- 仓库地址 -->
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </repository>
    </repositories>
</project>

bootstrap.yml

spring:
  application:
    name: order #配置服务名称
  #统一配置中心
  cloud:
      config:
        discovery:
          enabled: true
          service-id: CONFIG   #configServer 服务的名字
        profile: dev
      bus:
        trace:
          enabled: true
      stream:
        bindings:
          input: #消息名字
            group: order #消息分组  项目不管启动多少实例,都只有一个实例接收消息
            content-type: application/json #序列化
  redis:
    host: 192.168.3.233
    port: 6379
#配置Eureka
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/

order-dev.yml(统一配置中心)

spring:
  application:
    #配置服务名称
    name: order 
  #配置数据源
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    username: root
    password: 123456
    url: jdbc:mysql://localhost:3306/SpringCloud_Sell?characterEncoding=utf-8&useSSL=false
  jpa:
    show-sql: true
    #消息队列
  rabbitmq:
    host: 192.168.3.233
    username: guest
    password: guest
    port: 5672
# 配置Eureka
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka/
#配置端扣号
server:
  port: 8802
#自定义负载均衡规则
#PRODUCT:
#  ribbon:
#    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
env:
  dev4
girl: 
  name: lili
age: 24

JsonUtil

public class JsonUtil {
	private static ObjectMapper objectMapper = new ObjectMapper();

	/**
	 * json转换为对象
	 */
	public static Object fromJson(String string,Class classType){
		try {
			return objectMapper.readValue(string,classType);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * json转换为对象
	 */
	public static Object fromJson(String string,TypeReference typeReference){
		try {
			return objectMapper.readValue(string,typeReference);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
}

ProductInfoReceiver

/**
 * @Title
 * @Author zwj
 * @Date 2018/11/28
 * @Description
 */
@Component
@Slf4j
public class ProductInfoReceiver {
    private static final String PRODUCT_STOCK_TEMPLATE="product_stock_%s";
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    /**
     * 接收orderDTO对象消息
     * */
    @RabbitListener(queuesToDeclare = @Queue("productInfo"))
    public void process(String message) {
        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())
                            ,String.valueOf(productInfoOutput.getProductStock()));
        }
    }
}

3、测试

 

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/qq_29479041/article/details/84585465
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-05-07 22:07:37
  • 阅读 ( 1970 )
  • 分类:Redis

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢