Dubbo 2.7 整合SpringBoot

运行环境:

  • springboot 2.6.2
  • dubbo 2.7.15
  • mysql 8.0.23
  • jdk 1.8
  • nacos-client 2.0.3

项目结构:

父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>

    <groupId>com.harvey</groupId>
    <artifactId>dubbo-springboot</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>dubbo-service-client</module>
        <module>dubbo-service-storage</module>
        <module>dubbo-service-order</module>
    </modules>

    <properties>
        <dubbo.version>2.7.15</dubbo.version>
        <mysql.version>8.0.23</mysql.version>
    </properties>

    <dependencyManagement>
        <dependencies>
            <!--SpringBoot 依赖-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.6.2</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!--dubbo-->
            <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo-bom</artifactId>
                <version>${dubbo.version}</version>
                <type>pom</type>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

库表设计:

-- 1、创建tz_storage数据库
-- 2、创建tc_storage表
CREATE TABLE `tc_storage` (
    `storage_id` bigint unsigned NOT NULL,
    `product_code` varchar(255) COLLATE utf8mb4_bin NOT NULL,
    `quantity` int NOT NULL DEFAULT '0',
    `version` bigint unsigned NOT NULL DEFAULT '0',
    `product_name` varchar(255) COLLATE utf8mb4_bin NOT NULL,
    `product_unit` decimal(10,2) NOT NULL,
    PRIMARY KEY (`storage_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

-- 3、初始化数据
INSERT INTO `tz_storage`.`tc_storage` (`storage_id`, `product_code`, `quantity`, `version`, `product_name`, `product_unit`)
VALUES ('10001', '100010001', '100', '0', '华为Mate 40', '4599.00');
INSERT INTO `tz_storage`.`tc_storage` (`storage_id`, `product_code`, `quantity`, `version`, `product_name`, `product_unit`)
VALUES ('10002', '100020002', '100', '0', '小米6', '1499.00');
INSERT INTO `tz_storage`.`tc_storage` (`storage_id`, `product_code`, `quantity`, `version`, `product_name`, `product_unit`)
VALUES ('10003', '100030003', '100', '0', 'HUAWEI nova 7', '2999.00');
INSERT INTO `tz_storage`.`tc_storage` (`storage_id`, `product_code`, `quantity`, `version`, `product_name`, `product_unit`)
VALUES ('10004', '100040004', '100', '0', '苹果12', '7999.00');
INSERT INTO `tz_storage`.`tc_storage` (`storage_id`, `product_code`, `quantity`, `version`, `product_name`, `product_unit`)
VALUES ('10005', '100050005', '100', '0', 'OPPO Find X', '3999.00');
-- 1、创建tz_order数据库
-- 2、创建tc_order表
CREATE TABLE `tc_order` (
    `order_id` bigint unsigned NOT NULL,
    `order_num` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL,
    `product_code` varchar(50) COLLATE utf8mb4_bin NOT NULL,
    `product_unit` decimal(10,2) NOT NULL,
    `quantity` int NOT NULL DEFAULT '0',
    `user_id` bigint unsigned NOT NULL,
    PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin;

dubbo-service-client

接口定义(即要暴露的接口)

1、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>
        <artifactId>dubbo-springboot</artifactId>
        <groupId>com.harvey</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>dubbo-service-client</artifactId>
    <!--这里要加上个版本,否则其他模块引用不到-->
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

</project>

2、实体类

import java.io.Serializable;
import java.math.BigDecimal;

public class StorageDto implements Serializable {

    /**
     * 库存id
     */
    private Long storageId;

    /**
     * 订单ID
     */
    private Long orderId;
    /**
     * 商品编码
     */
    private String productCode;
    /**
     * 当前订单的购买数量
     */
    private Integer quantity;

    /**
     * 商品名称
     */
    private String productName;

    /**
     * 商品单价
     */
    private BigDecimal productUnit;

    /**
     * 版本号
     */
    private Long version;


    public Long getStorageId() {
        return storageId;
    }

    public void setStorageId(Long storageId) {
        this.storageId = storageId;
    }

    public Long getOrderId() {
        return orderId;
    }

    public void setOrderId(Long orderId) {
        this.orderId = orderId;
    }

    public String getProductCode() {
        return productCode;
    }

    public void setProductCode(String productCode) {
        this.productCode = productCode;
    }

    public Integer getQuantity() {
        return quantity;
    }

    public void setQuantity(Integer quantity) {
        this.quantity = quantity;
    }

    public String getProductName() {
        return productName;
    }

    public void setProductName(String productName) {
        this.productName = productName;
    }

    public BigDecimal getProductUnit() {
        return productUnit;
    }

    public void setProductUnit(BigDecimal productUnit) {
        this.productUnit = productUnit;
    }

    public Long getVersion() {
        return version;
    }

    public void setVersion(Long version) {
        this.version = version;
    }

}

3、接口定义

public interface StorageReduceDubboService {

    /**
     * 扣减库存
     * @param storageDto
     * @return
     */
    boolean reduceProductStorage(StorageDto storageDto);

    /**
     * 回退库存
     * @param storageDto
     * @return
     */
    boolean rollProductStorage(StorageDto storageDto);

    /**
     * 查询商品信息
     * @param productCode
     * @return
     */
    StorageDto getProduct(String productCode);

}

dubbo-service-storage

1、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>
        <artifactId>dubbo-springboot</artifactId>
        <groupId>com.harvey</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>dubbo-service-storage</artifactId>

    <dependencies>

        <dependency>
            <groupId>com.harvey</groupId>
            <artifactId>dubbo-service-client</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <!--web应用-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--数据库/JDBC操作-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>

        <!--dubbo支持-->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>${dubbo.version}</version>
        </dependency>
        <!--nacos支持-->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-registry-nacos</artifactId>
            <version>${dubbo.version}</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
            <version>2.0.3</version>
        </dependency>

    </dependencies>

</project>

2、启动类StorageApp.java

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class StorageApp {
    public static void main(String[] args) {
        SpringApplication.run(StorageApp.class, args);
    }
}

3、application.yml

server:
  port: 8888

spring:
  application:
    name: storage-service
  #数据源配置
  datasource:
    #通用配置
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/tz_storage?useUnicode=true&rewriteBatchedStatements=true&serverTimezone=Asia/Shanghai
    driver-class-name: com.mysql.cj.jdbc.Driver #com.mysql.jdbc.Driver

    #hikari数据源特性配置
    hikari:
      maximum-pool-size: 1000 #最大连接数,默认值10.
      minimum-idle: 200 #最小空闲连接,默认值10.
      connection-timeout: 60000 #连接超时时间(毫秒),默认值30秒.
      #空闲连接超时时间,默认值600000(10分钟),只有空闲连接数大于最大连接数且空闲时间超过该值,才会被释放
      #如果大于等于 max-lifetime 且 max-lifetime>0,则会被重置为0.
      idle-timeout: 600000
      max-lifetime: 3000000 #连接最大存活时间,默认值30分钟.设置应该比mysql设置的超时时间短
      connection-test-query: select 1 #连接测试查询


dubbo:
  application:
    name: ${spring.application.name} #应用名
  registry:
    address: nacos://127.0.0.1:8848?namespace=fecc85ab-4046-4579-bb33-1fe7e166be21
  protocol:
    name: dubbo
    port: -1 #dubbo服务暴露的端口
  scan:
    base-packages: com.harvey #扫描的包名
  provider:
    timeout: 5000
  consumer:
    timeout: 5000

4、业务接口的具体实现

StorageReduceService.java

public interface StorageReduceService {

    boolean reduceProductStorage(StorageDto storageDto);

    boolean rollProductStorage(StorageDto storageDto);

    StorageDto getProduct(String productCode);

}

StorageReduceServiceImpl.java

@Service("storageReduceService")
public class StorageReduceServiceImpl implements StorageReduceService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public boolean reduceProductStorage(StorageDto storageDto) {
        String sql = "update tc_storage set quantity = quantity - ?, version = version+1 where product_code = ? and version = ? and quantity > 0";
        return jdbcTemplate.update(sql, storageDto.getQuantity(), storageDto.getProductCode(), storageDto.getVersion()) > 0;
    }

    @Override
    public boolean rollProductStorage(StorageDto storageDto) {
        String sql = "update tc_storage set quantity = quantity + ?, version=version+1 where product_code = ? and version = ?";
        return jdbcTemplate.update(sql, storageDto.getQuantity(), storageDto.getProductCode(), storageDto.getVersion()) > 0;
    }

    @Override
    public StorageDto getProduct(String productCode) {
        String sql = "select * from tc_storage where product_code = ?";
        return jdbcTemplate.queryForObject(sql, new RowMapper<StorageDto>() {
            @Override
            public StorageDto mapRow(ResultSet resultSet, int i) throws SQLException {
                StorageDto storageDto = new StorageDto();
                storageDto.setProductCode(resultSet.getString("product_code"));
                storageDto.setProductName(resultSet.getString("product_name"));
                storageDto.setQuantity(resultSet.getInt("quantity"));
                storageDto.setVersion(resultSet.getLong("version"));
                storageDto.setStorageId(resultSet.getLong("storage_id"));
                storageDto.setProductUnit(resultSet.getBigDecimal("product_unit"));
                return storageDto;
            }
        }, productCode);
    }
}

5、暴露接口

StorageReduceDubboServiceImpl.java

@DubboService
public class StorageReduceDubboServiceImpl implements StorageReduceDubboService {


    @Autowired
    private StorageReduceService storageReduceService;

    /**
     * 扣减库存
     *
     * @param storageDto
     * @return
     */
    @Override
    public boolean reduceProductStorage(StorageDto storageDto) {
        return storageReduceService.reduceProductStorage(storageDto);
    }

    /**
     * 回退库存
     *
     * @param storageDto
     * @return
     */
    @Override
    public boolean rollProductStorage(StorageDto storageDto) {
        return storageReduceService.rollProductStorage(storageDto);
    }

    /**
     * 查询商品信息
     *
     * @param productCode
     * @return
     */
    @Override
    public StorageDto getProduct(String productCode) {
        return storageReduceService.getProduct(productCode);
    }
}

dubbo-service-order

1、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>
        <artifactId>dubbo-springboot</artifactId>
        <groupId>com.harvey</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>dubbo-service-order</artifactId>

    <dependencies>

        <dependency>
            <groupId>com.harvey</groupId>
            <artifactId>dubbo-service-client</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <!--web应用-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--数据库/JDBC操作-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>

        <!--dubbo支持-->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>${dubbo.version}</version>
        </dependency>
        <!--nacos支持-->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-registry-nacos</artifactId>
            <version>${dubbo.version}</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.nacos</groupId>
            <artifactId>nacos-client</artifactId>
            <version>2.0.3</version>
        </dependency>

    </dependencies>

</project>

2、启动类OrderApp.java

@SpringBootApplication
public class OrderApp {
    public static void main(String[] args) {
        SpringApplication.run(OrderApp.class, args);
    }
}

3、application.yml

server:
  port: 9090

spring:
  application:
    name: order-service
  #数据源配置
  datasource:
    #通用配置
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/tz_order?useUnicode=true&rewriteBatchedStatements=true&serverTimezone=Asia/Shanghai
    driver-class-name: com.mysql.cj.jdbc.Driver #com.mysql.jdbc.Driver

    #hikari数据源特性配置
    hikari:
      maximum-pool-size: 1000 #最大连接数,默认值10.
      minimum-idle: 200 #最小空闲连接,默认值10.
      connection-timeout: 60000 #连接超时时间(毫秒),默认值30秒.
      #空闲连接超时时间,默认值600000(10分钟),只有空闲连接数大于最大连接数且空闲时间超过该值,才会被释放
      #如果大于等于 max-lifetime 且 max-lifetime>0,则会被重置为0.
      idle-timeout: 600000
      max-lifetime: 3000000 #连接最大存活时间,默认值30分钟.设置应该比mysql设置的超时时间短
      connection-test-query: select 1 #连接测试查询

dubbo:
  application:
    name: ${spring.application.name} #应用名
  registry:
    address: nacos://127.0.0.1:8848?namespace=fecc85ab-4046-4579-bb33-1fe7e166be21
  protocol:
    name: dubbo
    port: -1 #dubbo服务暴露的端口
  scan:
    base-packages: com.harvey #扫描的包名
  provider:
    timeout: 5000
  consumer:
    timeout: 5000

4、工具类

/**
 * @Desc:   * 订单编码码生成器,生成32位数字编码,
 * @生成规则 1位单号类型+17位时间戳+14位(用户id加密&随机数)
 */
public final class OrderCoderUtil {


    /** 订单类别头 */
    private static final String ORDER_CODE = "1";
    /** 退货类别头 */
    private static final String RETURN_ORDER = "2";
    /** 退款类别头 */
    private static final String REFUND_ORDER = "3";
    /** 未付款重新支付别头 */
    private static final String AGAIN_ORDER = "4";
    /** 随即编码 */
    private static final int[] r = new int[]{7, 9, 6, 2, 8 , 1, 3, 0, 5, 4};
    /** 用户id和随机数总长度 */
    private static final int maxLength = 14;


    /**
     * 生成订单单号编码
     * @param userId
     */
    public static String getOrderCode(Long userId){
        return ORDER_CODE + getCode(userId);
    }


    /**
     * 生成退货单号编码
     * @param userId
     */
    public static String getReturnCode(Long userId){
        return RETURN_ORDER + getCode(userId);
    }


    /**
     * 生成退款单号编码
     * @param userId
     */
    public static String getRefundCode(Long userId){
        return REFUND_ORDER + getCode(userId);
    }

    /**
     * 未付款重新支付
     * @param userId
     */
    public static String getAgainCode(Long userId){
        return AGAIN_ORDER + getCode(userId);
    }



    /**
     * 更具id进行加密+加随机数组成固定长度编码
     */
    private static String toCode(Long id) {
        String idStr = id.toString();
        StringBuilder idsbs = new StringBuilder();
        for (int i = idStr.length() - 1 ; i >= 0; i--) {
            idsbs.append(r[idStr.charAt(i)-'0']);
        }
        return idsbs.append(getRandom(maxLength - idStr.length())).toString();
    }

    /**
     * 生成时间戳
     */
    private static String getDateTime(){
        DateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        return sdf.format(new Date());
    }

    /**
     * 生成固定长度随机码
     * @param n    长度
     */
    private static long getRandom(long n) {
        long min = 1,max = 9;
        for (int i = 1; i < n; i++) {
            min *= 10;
            max *= 10;
        }
        long rangeLong = (((long) (new Random().nextDouble() * (max - min)))) + min ;
        return rangeLong;
    }

    /**
     * 生成不带类别标头的编码
     * @param userId
     */
    private static synchronized String getCode(Long userId){
        userId = userId == null ? 10000 : userId;
        return getDateTime() + toCode(userId);
    }
}
public final class IdUtil {

    private static final String DATE_PATTERN = "yyyyMMdd";

    private IdUtil() {
    }

    /**
     * 生成18位数字
     * 说明:循环10万左右会有重复ID
     *
     * @return
     */
    public static Long generate18Number() {
        //随机生成一位整数
        int random = (int) (Math.random() * 9 + 1);
        String prefix = String.valueOf(random);
        //格式化日期,生成8位数字
        String middle = LocalDate.now().format(DateTimeFormatter.ofPattern(DATE_PATTERN));
        //生成uuid的hashCode值
        int hashCode = UUID.randomUUID().toString().hashCode();
        //可能为负数
        if (hashCode < 0) {
            hashCode = -hashCode;
        }
        String code = String.valueOf(hashCode);
        if (code.length() > 9) {
            hashCode = Integer.parseInt(code.substring(1));
        }
        String value = prefix + middle + String.format("%09d", hashCode);
        return Long.valueOf(value);
    }
}

5、持久化操作

OrderDao.java

public interface OrderDao {

    int saveOrder(OrderBO orderBO);

    List<OrderBO> findOrders(Long userId);
}

OrderDaoImpl.java

@Repository
public class OrderDaoImpl implements OrderDao {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public int saveOrder(OrderBO orderBO) {
        String saveSql = "insert into tc_order(order_id, order_num, product_code, product_unit, quantity, user_id) " +
                "values(?, ?, ?, ?, ?, ?)";
        return jdbcTemplate.update(saveSql, orderBO.getOrderId(), orderBO.getOrderNum(),
                orderBO.getProductCode(), orderBO.getProductUnit(), orderBO.getQuantity(), orderBO.getUserId());
    }

    @Override
    public List<OrderBO> findOrders(Long userId) {
        String querySql = "select * from tc_order where user_id = ?";
        List<Map<String, Object>> mapList = jdbcTemplate.queryForList(querySql, userId);
        List<OrderBO> orderBOList = new ArrayList();
        for(Map<String, Object> item : mapList){
            OrderBO orderBO = new OrderBO();
            orderBO.setOrderId(Long.parseLong(item.get("order_id").toString()));
            orderBO.setOrderNum(item.get("order_num").toString());
            orderBO.setUserId(Long.parseLong(item.get("user_id").toString()));
            orderBO.setProductCode(item.get("product_code").toString());
            orderBO.setProductUnit(new BigDecimal(item.get("product_unit").toString()));
            orderBO.setQuantity(Integer.parseInt(item.get("quantity").toString()));
            orderBO.setTotalPrice(new BigDecimal(item.get("product_unit").toString()).multiply(new BigDecimal(orderBO.getQuantity())));
            orderBOList.add(orderBO);
        }
        return orderBOList;
    }
}

实体类OrderBO

/**
 * 订单数据
 */
public class OrderBO implements Serializable {

    /**
     * 订单ID
     */
    private Long orderId;
    /**
     * 订单编号
     */
    private String orderNum;
    /**
     * 订单总价
     */
    private BigDecimal totalPrice;
    /**
     * 商品编码
     */
    private String productCode;
    /**
     * 商品单价
     */
    private BigDecimal productUnit;
    /**
     * 商品数量
     */
    private Integer quantity;

    /**
     * 用户id
     */
    private Long userId;

    public Long getOrderId() {
        return orderId;
    }

    public void setOrderId(Long orderId) {
        this.orderId = orderId;
    }

    public String getOrderNum() {
        return orderNum;
    }

    public void setOrderNum(String orderNum) {
        this.orderNum = orderNum;
    }

    public BigDecimal getTotalPrice() {
        return totalPrice;
    }

    public void setTotalPrice(BigDecimal totalPrice) {
        this.totalPrice = totalPrice;
    }

    public String getProductCode() {
        return productCode;
    }

    public void setProductCode(String productCode) {
        this.productCode = productCode;
    }

    public BigDecimal getProductUnit() {
        return productUnit;
    }

    public void setProductUnit(BigDecimal productUnit) {
        this.productUnit = productUnit;
    }

    public Integer getQuantity() {
        return quantity;
    }

    public void setQuantity(Integer quantity) {
        this.quantity = quantity;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    
}

6、业务操作

调用Dubbo接口完成业务操作。

OrderService.java

public interface OrderService {

    /**
     * 创建订单
     * @param userId
     * @return
     */
    String createOrder(Long userId, String productCode, Integer quantity);

    /**
     * 查询用户订单
     * @param userId
     * @return
     */
    List<OrderBO> listOrders(Long userId);

}

OrderServiceImpl.java

@Service
public class OrderServiceImpl implements OrderService {


    @Autowired
    private OrderDao orderDao;

    @DubboReference
    private StorageReduceDubboService storageReduceService;

    /**
     * 创建订单
     *
     * @param userId
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String createOrder(Long userId, String productCode, Integer quantity) {
        OrderBO orderBO = new OrderBO();
        orderBO.setUserId(userId);
        StorageDto productDto = storageReduceService.getProduct(productCode);
        orderBO.setProductCode(productDto.getProductCode());
        orderBO.setProductUnit(productDto.getProductUnit());
        orderBO.setQuantity(quantity);
        Long orderId = IdUtil.generate18Number();
        orderBO.setOrderId(orderId);
        String orderNumber = OrderCoderUtil.getOrderCode(userId);
        orderBO.setOrderNum(orderNumber);
        //保存订单
        orderDao.saveOrder(orderBO);
        //扣减库存
        StorageDto storageDto = new StorageDto();
        storageDto.setOrderId(orderId);
        storageDto.setStorageId(productDto.getStorageId());
        storageDto.setQuantity(quantity);
        storageDto.setVersion(productDto.getVersion());
        storageDto.setProductCode(productDto.getProductCode());
        storageReduceService.reduceProductStorage(storageDto);
        return orderNumber;
    }

    /**
     * 查询用户订单
     *
     * @param userId
     * @return
     */
    @Override
    public List<OrderBO> listOrders(Long userId) {
        return orderDao.findOrders(userId);
    }
}

7、Controller请求

OrderController.java

@RestController
public class OrderController {

    @Autowired
    private OrderService orderService;

    //POST http://localhost:9090/createOrder?userId=10020201&productCode=100010001&quantity=1
    @RequestMapping("/createOrder")
    public Map<String, Object> createOrder(Long userId, String productCode, Integer quantity) {
        String orderNum = orderService.createOrder(userId, productCode, quantity);
        Map<String, Object> resultMap = new HashMap();
        resultMap.put("msg", "创建订单成功");
        resultMap.put("orderNum", orderNum);
        return resultMap;
    }
}

测试运行

1)启动运行Nacos Server(注意项目中配置的命名空间、组等信息必须预先创建)

2)启动服务提供者dubbo-service-storage

3)启动服务消费者dubbo-service-order

4)服务已注册到Nacos后(Nacos查看),调用controller请求创建订单验证

相关的代码可以下载:代码提取

注册中心使用Zookeeper

本人演示时使用的Zookeeper版本为3.4.8。

相关代码可以下载:代码提取

 

posted @ 2022-03-27 23:16  残城碎梦  阅读(690)  评论(0编辑  收藏  举报