springcloud整合seata、nacos

一、所需环境

win10、idea、maven3.6.0、jdk1.8、nacos-server-1.4.4、seata-server-1.5.1、mysql5.7.26

二、为什么需要Seata?

  1. Seata是一款开源的分布式事务解决方案,致力于提供高性能简单易用的分布式事务服务;

  2. 在我们没有使用分布式服务的时候,我们程序与数据库大多是1:1,或者1:N的,也就是说,一个程序对应一个数据库或一个程序对应一个数据库集群,通常这个时候,我们需要对多张表进行修改操作时,我们都会为其增添事务,以达到要么都成功,要么都失败的目的;

  3. 而当我们引用分布式服务的时候,我们程序与数据库的关系将变得复杂,每一个服务都将会拥有属于自己的数据库,这时候就形成了N : N的关系,也就是多个微服务,对应多个数据库;

    • 在这样的情况下,当我们的逻辑业务需要调用到其它微服务的时候,如何保证这一业务逻辑的事务就变成了一个问题,例如;

          @Override
          public Integer createOrder(Order order) {
              // 这里使用了OpenFeign调用了storage微服务,用来调用storage微服务的扣减商品库存的api
              log.info("*****deduction of goods : {} begins",order.getCommodityCode());
              storageService.reduceStorage(order.getCommodityCode(),order.getCount());
              log.info("*****deduction of goods : {} ends",order.getCommodityCode());
      
              // 这里使用了OpenFeign调用了accout微服务,用来调用accout微服务的扣减余额的api
              log.info("****deduction of balance : {} begins",order.getUserId());
              accountService.deductAccount(order.getUserId(),order.getMoney());
              log.info("****deduction of balance : {} ends",order.getUserId());
      
              // 手动造成一个 by zero异常
              int age = 10 /0 ;
      
              // 创建订单
              log.info("****order creation begins");
              Integer orderId = orderMapper.createOrder(order);
              log.info("****order : {} creation ends",orderId);
              return orderId;
          }
      
      • 以上案例存在一个非常致命的问题,在没有使用事务的时候,storage微服务的商品库存会被减去,accout微服务的用户会被扣钱,但是order微服务的订单,却因为中途发生了异常,而没有生成对应的订单,也就是说,商品扣了,钱给了,但是没有订单,不给发货,这是一个很致命的问题;
      • 可能会有同学说,那就加事务呗,@Transaction多简单呐,加上不就得了嘛;
        • 想法没有错,但是这里的情况是分布式微服务,@Transaction已经爱莫能助了;
        • 想直接使用@Transaction来控制多个微服务的事务,无异于,你搁某宝买东西发生了异常,却要求人某东一起跟着回滚,没这个理昂;
      • 所以,为了解决上述问题,Seata出现了;
      • Seata的详解请移步官网,在这里一一写下的话,篇幅就太多了;

三、如何整合Seata与Nacos

  1. 下载seata-server,我这里下载的是seata的1.5.1版本,算是比较新的了;

在这里插入图片描述

  1. 下载nacos-server,我下载的是1.4.4版本;

在这里插入图片描述

  1. 分别解压以上两个服务的压缩包;

1.nacos配置并启动

  1. 进入nacos-server的conf目录,打开application.properties文件,在33-41行处添加如下信息;
#*************** Config Module Related Configurations ***************#
### If use MySQL as datasource:
spring.datasource.platform=mysql

### Count of DB:
db.num=1 

### Connect URL of DB:
db.url.0=jdbc:mysql://127.0.0.1:3306/nacos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
db.user.0=root
db.password.0=root

注意数据库用户名和密码,修改为自己的;

  1. 创建nacos数据库,并执行conf文件夹下的nacos-mysql.sql文件,生成对应的表;

    在这里插入图片描述

  2. 进入nacos目录下的bin目录,修改startup.cmd文件;

    • 将第26行修改为

      set MODE="standalone"
      

      默认为cluster;

  3. 修改后,直接双击startup.cmd即可启动nacos;

  4. 启动成功后,进入控制台页面;

    • http://localhost:8848/nacos

      在这里插入图片描述

    账户名和密码皆为 nacos

2.seata配置并启动

  1. 进入seata的conf目录,并打开application.yaml文件,配置如下;

    server:
      port: 7091
    
    spring:
      application:
        name: seata-server
    
    logging:
      config: classpath:logback-spring.xml
      file:
        path: ${user.home}/logs/seata
      extend:
        logstash-appender:
          destination: 127.0.0.1:4560
        kafka-appender:
          bootstrap-servers: 127.0.0.1:9092
          topic: logback_to_logstash
    
    console:
      user:
        username: seata
        password: seata
    
    seata:
      config:
        # support: nacos, consul, apollo, zk, etcd3
        # 注意事项,官方建议nacos版本在1.2.0及以上版本
        type: nacos
        nacos:
          server-addr: 127.0.0.1:8848
          namespace:  # 不写则默认为public名称空间
          group: SEATA_GROUP
          username: nacos # nacos的账号密码
          password: nacos
          ##if use MSE Nacos with auth, mutex with username/password attribute
          #access-key: ""
          #secret-key: ""
          data-id: seataServer.properties
      registry:
        # support: nacos, eureka, redis, zk, consul, etcd3, sofa
        type: nacos
        nacos:
          application: seata-server  # 指定注册至nacos注册中心的服务名,需要和${spring.application.name} 保持一致
          server-addr: 127.0.0.1:8848
          group: SEATA_GROUP
          namespace:
          cluster: default # 指定seata注册值nacos的集群名为default
          username: nacos
          password: nacos
          ##if use MSE Nacos with auth, mutex with username/password attribute
          #access-key: ""
          #secret-key: ""
      store:
        # support: file 、 db 、 redis
        # 注意数据库版本为5.7.26 , 使用8.0.12时报错Could not retrieve transation read-only status server
        mode: db
        db:
          datasource: druid
          db-type: mysql
          driver-class-name: com.mysql.jdbc.Driver
          url: jdbc:mysql://127.0.0.1:3306/seata?rewriteBatchedStatements=true&useUnicode=true
          user: root
          password: root
          min-conn: 5
          max-conn: 100
          global-table: global_table
          branch-table: branch_table
          lock-table: lock_table
          distributed-lock-table: distributed_lock
          query-limit: 100
          max-wait: 5000
    #  server:
    #    service-port: 8091 #If not configured, the default is '${server.port} + 1000'
      security:
        secretKey: SeataSecretKey0c382ef121d778043159209298fd40bf3850a017
        tokenValidityInMilliseconds: 1800000
        ignore:
          urls: /,/**/*.css,/**/*.js,/**/*.html,/**/*.map,/**/*.svg,/**/*.png,/**/*.ico,/console-fe/public/**,/api/v1/auth/login
    

    注意,在store存储的地方,将数据库用户名和密码修改为自己的;

    • 若本地没有mysql5.7.26版本,且启动seata时会报错Could not retrieve transation read-only status server;
    • 则将store下的mode的值改为file即可;
  2. 在数据库中创建seata数据库(若store存储模式不是db的则可以跳过该步骤)

    1. 执行以下脚本,生成对应数据表;

      -- -------------------------------- The script used when storeMode is 'db' --------------------------------
      -- the table to store GlobalSession data
      CREATE TABLE IF NOT EXISTS `global_table`
      (
          `xid`                       VARCHAR(128) NOT NULL,
          `transaction_id`            BIGINT,
          `status`                    TINYINT      NOT NULL,
          `application_id`            VARCHAR(32),
          `transaction_service_group` VARCHAR(32),
          `transaction_name`          VARCHAR(128),
          `timeout`                   INT,
          `begin_time`                BIGINT,
          `application_data`          VARCHAR(2000),
          `gmt_create`                DATETIME,
          `gmt_modified`              DATETIME,
          PRIMARY KEY (`xid`),
          KEY `idx_status_gmt_modified` (`status` , `gmt_modified`),
          KEY `idx_transaction_id` (`transaction_id`)
      ) ENGINE = InnoDB
        DEFAULT CHARSET = utf8mb4;
      
      -- the table to store BranchSession data
      CREATE TABLE IF NOT EXISTS `branch_table`
      (
          `branch_id`         BIGINT       NOT NULL,
          `xid`               VARCHAR(128) NOT NULL,
          `transaction_id`    BIGINT,
          `resource_group_id` VARCHAR(32),
          `resource_id`       VARCHAR(256),
          `branch_type`       VARCHAR(8),
          `status`            TINYINT,
          `client_id`         VARCHAR(64),
          `application_data`  VARCHAR(2000),
          `gmt_create`        DATETIME(6),
          `gmt_modified`      DATETIME(6),
          PRIMARY KEY (`branch_id`),
          KEY `idx_xid` (`xid`)
      ) ENGINE = InnoDB
        DEFAULT CHARSET = utf8mb4;
      
      -- the table to store lock data
      CREATE TABLE IF NOT EXISTS `lock_table`
      (
          `row_key`        VARCHAR(128) NOT NULL,
          `xid`            VARCHAR(128),
          `transaction_id` BIGINT,
          `branch_id`      BIGINT       NOT NULL,
          `resource_id`    VARCHAR(256),
          `table_name`     VARCHAR(32),
          `pk`             VARCHAR(36),
          `status`         TINYINT      NOT NULL DEFAULT '0' COMMENT '0:locked ,1:rollbacking',
          `gmt_create`     DATETIME,
          `gmt_modified`   DATETIME,
          PRIMARY KEY (`row_key`),
          KEY `idx_status` (`status`),
          KEY `idx_branch_id` (`branch_id`),
          KEY `idx_xid_and_branch_id` (`xid` , `branch_id`)
      ) ENGINE = InnoDB
        DEFAULT CHARSET = utf8mb4;
      
      CREATE TABLE IF NOT EXISTS `distributed_lock`
      (
          `lock_key`       CHAR(20) NOT NULL,
          `lock_value`     VARCHAR(20) NOT NULL,
          `expire`         BIGINT,
          primary key (`lock_key`)
      ) ENGINE = InnoDB
        DEFAULT CHARSET = utf8mb4;
      
      INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('AsyncCommitting', ' ', 0);
      INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryCommitting', ' ', 0);
      INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('RetryRollbacking', ' ', 0);
      INSERT INTO `distributed_lock` (lock_key, lock_value, expire) VALUES ('TxTimeoutCheck', ' ', 0);
      
    2. 在seata目录下的bin目录中,双击seata-server.bat即可启动seata,注意,在启动seata前一定要先启动nacos;

    3. 启动成功后,访问控制台页面;

    4. http://localhost:7091/#/login

    在这里插入图片描述

    用户名和密码皆为seata

    1. 且nacos的控制台中可以看到我们所注册的seata服务;

      在这里插入图片描述

四、springcloud整合seata、nacos案例演示

1、创建一个maven父工程springcloud-seata-demo

  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">
      <modelVersion>4.0.0</modelVersion>
    
      <groupId>com.wp.springcloud</groupId>
      <artifactId>springcloud</artifactId>
      <version>1.0-SNAPSHOT</version>
      <packaging>pom</packaging>
      <name>Maven</name>
        
      <!-- 统一jar包版本 -->
      <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <junit.version>4.12</junit.version>
        <lombok.version>1.16.18</lombok.version>
        <log4j.version>1.2.17</log4j.version>
        <mysql.version>5.1.47</mysql.version>
        <druid.version>1.1.16</druid.version>
        <mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
      </properties>
        
      <!-- 子模块继承之后,提供作用:锁定版本+子module不用写groupId和version -->
      <dependencyManagement>
        <dependencies>
          <!-- spring boot 2.2.2 -->
          <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.2.2.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
          </dependency>
          <!-- spring cloud Hoxton.SR1 -->
          <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Hoxton.SR1</version>
            <type>pom</type>
            <scope>import</scope>
          </dependency>
          <!-- spring cloud alibaba 2.1.0.RELEASE -->
          <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2.1.0.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
          </dependency>
    
          <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
          </dependency>
    
          <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>${druid.version}</version>
          </dependency>
    
          <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>${mybatis.spring.boot.version}</version>
          </dependency>
    
          <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
          </dependency>
    
          <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
          </dependency>
    
          <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
            <optional>true</optional>
          </dependency>
    
        </dependencies>
      </dependencyManagement>
    
    
      <build>
        <plugins>
          <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
              <fork>true</fork>
              <addResources>true</addResources>
            </configuration>
          </plugin>
        </plugins>
      </build>
    </project>
    

2、在父工程下创建cloud-api-commons

  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>springcloud</artifactId>
            <groupId>com.wp.springcloud</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>cloud-api-commons</artifactId>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
                <scope>runtime</scope>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>cn.hutool</groupId>
                <artifactId>hutool-all</artifactId>
                <version>5.1.0</version>
            </dependency>
        </dependencies>
    
    </project>
    
  2. 创建实体类

    package com.wp.www.entity;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class CommonResult<T> {
        private Integer code;
        private String message;
        private T data;
    
        public CommonResult(Integer code, String message) {
            this(code,message,null);
        }
    }
    

    此工程用来统一返回所需的实体类;

3、创建cloudalibaba-seata-order8001

  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>springcloud</artifactId>
            <groupId>com.wp.springcloud</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>cloudalibaba-seata-order</artifactId>
    
        <dependencies>
            <!--这里将以下两个包从starter中排除并重新引入的原因是,starter中的版本,与我们自己所下载的seata服务版本不一致-->
            <dependency>
                <groupId>io.seata</groupId>
                <artifactId>seata-spring-boot-starter</artifactId>
                <version>1.5.1</version>
            </dependency>
            <dependency>
                <groupId>io.seata</groupId>
                <artifactId>seata-all</artifactId>
                <version>1.5.1</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-seata</artifactId>
                <exclusions>
                    <exclusion>
                        <groupId>io.seata</groupId>
                        <artifactId>seata-spring-boot-starter</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>io.seata</groupId>
                        <artifactId>seata-all</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <!--feign-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
            <!--nacos-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            </dependency>
            <!-- SpringBoot整合Web组件+actuator -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
    
            <!-- https://mvnrepository.com/artifact/org.mybatis.spring.boot/mybatis-spring-boot-starter -->
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>2.1.3</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.37</version>
            </dependency>
    
            <!--日常通用jar包配置-->
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>com.wp.springcloud</groupId>
                <artifactId>cloud-api-commons</artifactId>
                <version>${project.version}</version>
            </dependency>
    
        </dependencies>
    
    </project>
    
  2. application.yaml

    server:
      port: 8001
    
    spring:
      application:
        name: cloudalibaba-seata-order
      cloud:
        nacos:
          discovery:  # 服务注册中心
            server-addr: 127.0.0.1:8848
        alibaba:
          seata: # 大坑,只有在此处配置tx-service-group才能生效
            tx-service-group: my-test-group
      datasource:
        username: root # 数据库用户名和密码修改为自己的
        password: root
        url: jdbc:mysql://127.0.0.1:3306/seata_order
        driver-class-name: com.mysql.jdbc.Driver
        type: com.alibaba.druid.pool.DruidDataSource
    seata:
      service:
        vgroup-mapping:
          my-test-group: default  # 指定事务分组至集群映射关系,即映射到哪一个seata-server集群上,需与server端注册到Nacos的cluster保持一致
      registry:
        type: nacos
        nacos:
          server-addr: 127.0.0.1:8848
          application: seata-server
          group: SEATA_GROUP
      enable-auto-data-source-proxy: true
    
    mybatis:
      configuration:
        map-underscore-to-camel-case: true
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
      mapper-locations: classpath:mapper/*.xml
    
  3. 主启动类

    package com.wp.www;
    
    import io.seata.spring.annotation.datasource.EnableAutoDataSourceProxy;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
    import org.springframework.cloud.openfeign.EnableFeignClients;
    
    @SpringBootApplication
    @EnableDiscoveryClient
    @MapperScan(value = {"com.wp.www.repository"})
    @EnableFeignClients
    @EnableAutoDataSourceProxy
    public class OrderMain8001 {
        public static void main(String[] args) {
            SpringApplication.run(OrderMain8001.class,args);
        }
    }
    
  4. 业务类

    1. repository包下

      package com.wp.www.repository;
      
      import com.wp.www.entity.order.Order;
      
      public interface OrderMapper {
          /* 创建订单并返回主键ID */
          Integer createOrder(Order order);
      }
      
    2. service报下

      1. interface

        package com.wp.www.service;
        
        import com.wp.www.entity.CommonResult;
        import org.springframework.cloud.openfeign.FeignClient;
        import org.springframework.web.bind.annotation.GetMapping;
        import org.springframework.web.bind.annotation.PathVariable;
        
        import java.math.BigDecimal;
        
        @FeignClient(value = "cloudalibaba-seata-accout")
        public interface AccountService {
            @GetMapping("/account/{userId}/{money}")
            public CommonResult deductAccount(@PathVariable("userId") String userId, @PathVariable("money") BigDecimal money);
        }
        
        package com.wp.www.service;
        
        import com.wp.www.entity.order.Order;
        
        public interface OrderService {
            Integer createOrder(Order order);
        }
        
        package com.wp.www.service;
        
        import com.wp.www.entity.CommonResult;
        import org.springframework.cloud.openfeign.FeignClient;
        import org.springframework.web.bind.annotation.GetMapping;
        import org.springframework.web.bind.annotation.PathVariable;
        
        @FeignClient(value = "cloudalibaba-seata-storage")
        public interface StorageService {
            @GetMapping("/storage/{commodityCode}/{count}")
            public CommonResult reduceStorage(@PathVariable("commodityCode") String commodityCode, @PathVariable("count") Integer count);
        }
        
      2. impl

        package com.wp.www.service.impl;
        
        import com.wp.www.entity.order.Order;
        import com.wp.www.repository.OrderMapper;
        import com.wp.www.service.AccountService;
        import com.wp.www.service.OrderService;
        import com.wp.www.service.StorageService;
        import io.seata.core.context.RootContext;
        import io.seata.spring.annotation.GlobalTransactional;
        import lombok.extern.slf4j.Slf4j;
        import org.springframework.stereotype.Service;
        
        import javax.annotation.Resource;
        
        @Service
        @Slf4j
        public class OrderServiceImpl implements OrderService {
        
            @Resource
            private OrderMapper orderMapper;
        
            @Resource
            private AccountService accountService;
        
            @Resource
            private StorageService storageService;
        
            @GlobalTransactional(name = "create-order",rollbackFor = {Exception.class})
            @Override
            public Integer createOrder(Order order) {
                log.info("*****全局事务xid:{}", RootContext.getXID());
        
                log.info("*****deduction of goods : {} begins",order.getCommodityCode());
                storageService.reduceStorage(order.getCommodityCode(),order.getCount());
                log.info("*****deduction of goods : {} ends",order.getCommodityCode());
        
                log.info("****deduction of balance : {} begins",order.getUserId());
                accountService.deductAccount(order.getUserId(),order.getMoney());
                log.info("****deduction of balance : {} ends",order.getUserId());
        
                // int age = 10 /0 ; // 若需要测试异常,将此异常打开即可
        
                log.info("****order creation begins");
                Integer orderId = orderMapper.createOrder(order);
                log.info("****order : {} creation ends",orderId);
                return orderId;
            }
        }
        

        在service中的AccountService与StorageService是结合OpenFeign来调用其它微服务的;

    3. controller包下

      package com.wp.www.controller;
      
      import com.wp.www.entity.CommonResult;
      import com.wp.www.entity.order.Order;
      import com.wp.www.service.OrderService;
      import org.springframework.web.bind.annotation.PostMapping;
      import org.springframework.web.bind.annotation.RequestBody;
      import org.springframework.web.bind.annotation.RestController;
      
      import javax.annotation.Resource;
      
      @RestController
      public class OrderController {
      
          @Resource
          private OrderService orderService;
      
          @PostMapping("/order")
          public CommonResult<Order> creatOrder(@RequestBody Order order){
              orderService.createOrder(order);
              return new CommonResult(200,"订单创建成功",order);
          }
      }
      
  5. 在资源文件夹下创建mapper文件夹

    1. OrderMapper.xml

      <?xml version="1.0" encoding="UTF-8" ?>
      <!DOCTYPE mapper
              PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
              "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
      
      <mapper namespace="com.wp.www.repository.OrderMapper">
      
          <insert id="createOrder" useGeneratedKeys="true" keyProperty="orderId">
              insert into order_tbl values (null,#{userId},#{commodityCode},#{count},#{money})
          </insert>
      </mapper>
      

4、另外根据cloudalibaba-seata-order8001分别创建两个微服务

  1. cloudalibaba-seata-account8002

  2. cloudalibaba-seata-storage8003

    具体创建细节不再写在该篇幅中

案例代码已上传至gitee

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值