三天学会阿里分布式事务框架Seata-SpringCloud Alibaba分布式基础案例搭建

锋哥原创的分布式事务框架Seata视频教程:

实战阿里分布式事务框架Seata视频教程(无废话,通俗易懂版)_哔哩哔哩_bilibili实战阿里分布式事务框架Seata视频教程(无废话,通俗易懂版)共计10条视频,包括:1 阿里分布式事务框架Seata简介、2 分布式事务简介、3 SpringCloud Alibaba分布式基础案例搭建等,UP主更多精彩视频,请关注UP账号。icon-default.png?t=N7T8https://www.bilibili.com/video/BV1Uf4y1579F/我们模拟一个简单下单业务,客户端调用rest对外服务,rest服务再调用订单服务实现创建订单和账户服务实现账户扣钱操作,最终来完整下单业务;

2.1 案例架构设计

所有服务都注册到nacos中,方便feign远程调用;订单服务,账户服务各自有独立数据库;架构设计如下图:

整体项目结构如下图:

seatatest是父项目,主要是做一些依赖管理,依赖版本管理,管理所有子module项目;

seata-common子项目,主要是引入其他子项目需要的公共依赖,以及公共实体,工具类,配置类的统一封装;

seata-order子项目,主要提供订单服务,生成订单;

seata-account子项目,主要提供账户服务,根据订单扣钱操作;

seata-web子项目,主要处理客户端下单请求,feign远程调用order,和account服务接口,最终完成下单处理;

2.2 数据库设计

我们新建两个数据库,分别是db_order(订单数据库),db_account(账户数据库),

db_order数据库里面新建表t_order订单表:

CREATE TABLE `t_order` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `orderNo` varchar(100) DEFAULT NULL,
  `userId` int(11) DEFAULT NULL,
  `count` int(11) DEFAULT NULL,
  `amount` int(11) DEFAULT NULL,
  `remark` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8

db_account数据库里面新建表t_account用户账户表:

CREATE TABLE `t_account` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `userId` int(11) DEFAULT NULL,
  `balance` int(11) DEFAULT NULL,
  `remark` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8

插入数据:

insert into `t_account` (`id`, `userId`, `balance`, `remark`) values('1','1','2000','jack的账户');
insert into `t_account` (`id`, `userId`, `balance`, `remark`) values('2','2','1000','marry的账户');

2.3 seatatest父项目搭建

seatatest是父项目,主要是做一些依赖管理,依赖版本管理,管理所有子module项目;

注意,它的packaging类型是pom

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.java1234</groupId>
    <artifactId>seatatest</artifactId>
    <packaging>pom</packaging>
    <version>1.0-SNAPSHOT</version>
    <modules>
        <module>seata-common</module>
        <module>seata-order</module>
        <module>seata-account</module>
        <module>seata-web</module>
    </modules>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <druid.version>1.1.10</druid.version>
        <spring-cloud.version>Hoxton.SR8</spring-cloud.version>
        <springboot.version>2.3.2.RELEASE</springboot.version>
        <springcloudalibaba.version>2.2.4.RELEASE</springcloudalibaba.version>
        <fastjson.version>1.2.35</fastjson.version>
        <commons-lang3.version>3.6</commons-lang3.version>
        <seata-common.version>1.0-SNAPSHOT</seata-common.version>
        <mybatis.version>2.1.0</mybatis.version>
    </properties>

    <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>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${springboot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>${springcloudalibaba.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
            <!-- 连接池 -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>${druid.version}</version>
            </dependency>

            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>${fastjson.version}</version>
            </dependency>

            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
                <version>${commons-lang3.version}</version>
            </dependency>

            <dependency>
                <groupId>com.java1234</groupId>
                <artifactId>seata-common</artifactId>
                <version>${seata-common.version}</version>
            </dependency>

            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>${mybatis.version}</version>
            </dependency>

        </dependencies>
    </dependencyManagement>


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>


</project>

2.4 seata-common子项目搭建

seata-common子项目,主要是引入其他子项目需要的公共依赖,以及公共实体,工具类,配置类的统一封装;

项目结构:

<?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>seatatest</artifactId>
        <groupId>com.java1234</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>seata-common</artifactId>

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

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

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

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


        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
        </dependency>

        <!-- spring boot redis 缓存引入 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!-- lettuce pool 缓存连接池 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
        </dependency>

        <dependency>
            <groupId>commons-codec</groupId>
            <artifactId>commons-codec</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>




    </dependencies>


</project>

订单实体Order

package com.java1234.entity;

/**订单表实体
 * @author java1234_小锋
 * @site www.java1234.com
 * @company 南通小锋网络科技有限公司
 * @create 2021-07-13 10:26
 */
public class Order {

    private Integer id; // 编号

    private String orderNo; // 订单号

    private Integer userId; // 用户编号

    private Integer count; // 购买数量

    private Integer amount; // 购买金额

    private String remark; // 备注

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getOrderNo() {
        return orderNo;
    }

    public void setOrderNo(String orderNo) {
        this.orderNo = orderNo;
    }

    public Integer getUserId() {
        return userId;
    }

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

    public Integer getCount() {
        return count;
    }

    public void setCount(Integer count) {
        this.count = count;
    }

    public Integer getAmount() {
        return amount;
    }

    public void setAmount(Integer amount) {
        this.amount = amount;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }
}

账户实体Account

package com.java1234.entity;

/**
 * 用户账户表
 * @author java1234_小锋
 * @site www.java1234.com
 * @company 南通小锋网络科技有限公司
 * @create 2021-07-13 10:36
 */
public class Account {

    private Integer id; // 编号

    private Integer userId; // 用户编号

    private Integer balance; // 账户余额

    private String remark; // 备注

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getUserId() {
        return userId;
    }

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

    public Integer getBalance() {
        return balance;
    }

    public void setBalance(Integer balance) {
        this.balance = balance;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }
}

2.5 seata-order子项目搭建

seata-order子项目,主要提供订单服务,生成订单;

项目结构:

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>seatatest</artifactId>
        <groupId>com.java1234</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>seata-order</artifactId>
    
    <dependencies>
        <dependency>
            <groupId>com.java1234</groupId>
            <artifactId>seata-common</artifactId>
        </dependency>



    </dependencies>


</project>

application.yml

server:
  port: 8081
  servlet:
    context-path: /

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db_order?serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
  application:
    name: seata-order

mybatis:
  mapper-locations: classpath:mybatis/mapper/*.xml

启动类OrderApplication

package com.java1234;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@MapperScan("com.java1234.mapper")
@EnableDiscoveryClient
public class OrderApplication {

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

}

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.java1234.mapper.OrderMapper">

    <select id="createOrder" parameterType="com.java1234.entity.Order" >
        insert into t_order values(null,#{orderNo},#{userId},#{count},#{amount},#{remark})
    </select>
</mapper>

OrderMapper接口:

package com.java1234.mapper;

import com.java1234.entity.Order;

/**
 * @author java1234_小锋
 * @site www.java1234.com
 * @company 南通小锋网络科技有限公司
 * @create 2021-07-13 10:43
 */
public interface OrderMapper {

    /**
     * 创建订单
     * @param order
     */
    void createOrder(Order order);


}

OrderService接口:

package com.java1234.service;

import com.java1234.entity.Order;

/**
 * 订单service接口
 * @author java1234_小锋
 * @site www.java1234.com
 * @company 南通小锋网络科技有限公司
 * @create 2021-07-14 11:00
 */
public interface OrderService {

    /**
     * 创建订单
     * @param order
     */
    void createOrder(Order order);

}

OrderServiceImpl实现类:

package com.java1234.service.impl;

import com.java1234.entity.Order;
import com.java1234.mapper.OrderMapper;
import com.java1234.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @author java1234_小锋
 * @site www.java1234.com
 * @company 南通小锋网络科技有限公司
 * @create 2021-07-14 11:02
 */
@Service("orderService")
public class OrderServiceImpl implements OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Override
    public void createOrder(Order order) {
        orderMapper.createOrder(order);
    }
}

OrderController

package com.java1234.controller;

import com.java1234.entity.Order;
import com.java1234.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.UUID;

/**
 * @author java1234_小锋
 * @site www.java1234.com
 * @company 南通小锋网络科技有限公司
 * @create 2021-07-14 11:13
 */
@RestController
@RequestMapping("/seata")
public class OrderController {

    @Autowired
    private OrderService orderService;

    /**
     * 创建订单
     * @param order
     * @return
     */
    @PostMapping("/createOrder")
    public boolean createOrder(@RequestBody Order order){
        System.out.println("order:"+order);
        order.setOrderNo(UUID.randomUUID().toString());  // 生成订单ID
        orderService.createOrder(order);
        return true;
    }
}

2.6 seata-account子项目搭建

seata-account子项目,主要提供账户服务,根据订单扣钱操作;

项目结构:

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>seatatest</artifactId>
        <groupId>com.java1234</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>seata-account</artifactId>

    <dependencies>
        <dependency>
            <groupId>com.java1234</groupId>
            <artifactId>seata-common</artifactId>
        </dependency>
    </dependencies>


</project>

application.yml

server:
  port: 8082
  servlet:
    context-path: /

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/db_account?serverTimezone=Asia/Shanghai
    username: root
    password: 123456
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
  application:
    name: seata-account

mybatis:
  mapper-locations: classpath:mybatis/mapper/*.xml

AccountApplication启动类:

package com.java1234;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@SpringBootApplication
@MapperScan("com.java1234.mapper")
@EnableDiscoveryClient
public class AccountApplication {

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

}

AccountMapper.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.java1234.mapper.AccountMapper">

    <select id="decrease" parameterType="Map" >
        UPDATE t_account SET balance=balance-#{amount} WHERE userId=#{userId}
    </select>
</mapper>

AccountMapper接口:

package com.java1234.mapper;


import java.util.Map;

/**
 * 账户Mapper接口
 * @author java1234_小锋
 * @site www.java1234.com
 * @company 南通小锋网络科技有限公司
 * @create 2021-07-13 10:43
 */
public interface AccountMapper {

    /**
     * 账户扣钱
     */
    void decrease(Map map);


}

AccountService接口:

package com.java1234.service;

import java.util.Map;

/**
 * 账户service接口
 * @author java1234_小锋
 * @site www.java1234.com
 * @company 南通小锋网络科技有限公司
 * @create 2021-07-15 12:58
 */
public interface AccountService {

    /**
     * 账户扣钱
     */
    void decrease(Map map);
}

`AccountServiceImpl`接口实现类:

package com.java1234.service.impl;

import com.java1234.mapper.AccountMapper;
import com.java1234.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;

/**
 * 账户Service实现类
 * @author java1234_小锋
 * @site www.java1234.com
 * @company 南通小锋网络科技有限公司
 * @create 2021-07-15 13:00
 */
@Service("accountService")
public class AccountServiceImpl implements AccountService {

    @Autowired
    private AccountMapper accountMapper;

    @Override
    public void decrease(Map map) {
        accountMapper.decrease(map);
    }
}

AccountController

package com.java1234.controller;

import com.java1234.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * 账户Controller
 * @author java1234_小锋
 * @site www.java1234.com
 * @company 南通小锋网络科技有限公司
 * @create 2021-07-15 13:06
 */
@RestController
@RequestMapping("/account")
public class AccountController {

    @Autowired
    private AccountService accountService;

    /**
     * 给指定用户账户扣钱
     * @param amount
     * @param userId
     * @return
     */
    @PostMapping("/decrease")
    public boolean decrease(@RequestParam("amount")Integer amount, @RequestParam("userId")Integer userId){
        System.out.println("amount:"+amount+",userId:"+userId);

        Map<String,Object> map=new HashMap<>();
        map.put("amount",amount);
        map.put("userId",userId);

        accountService.decrease(map);
        return true;

    }

}

2.7 seata-web子项目搭建

seata-web子项目,主要处理客户端下单请求,feign远程调用order,和account服务接口,最终完成下单处理;

项目结构:

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>seatatest</artifactId>
        <groupId>com.java1234</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>seata-web</artifactId>

    <dependencies>

        <dependency>
            <groupId>com.java1234</groupId>
            <artifactId>seata-common</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

    </dependencies>


</project>

application.yml

server:
  port: 80
  servlet:
    context-path: /


spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
  application:
    name: seata-web

WebApplication

package com.java1234;


import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication(exclude= {DataSourceAutoConfiguration.class})
@EnableFeignClients(basePackages = "com.java1234.feign")
@EnableDiscoveryClient
public class WebApplication {

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

}

OrderFeignService

package com.java1234.feign;

import com.java1234.entity.Order;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

/**
 * 订单接口feign远程调用
 * @author java1234_小锋
 * @site www.java1234.com
 * @company 南通小锋网络科技有限公司
 * @create 2021-07-16 10:55
 */
@FeignClient("seata-order")
public interface OrderFeignService {

    /**
     * 创建订单
     * @param order
     * @return
     */
    @PostMapping("/seata/createOrder")
    public boolean createOrder(@RequestBody Order order);

}

AccountFeignService

package com.java1234.feign;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

/**
 * 账号接口feign远程调用
 * @author java1234_小锋
 * @site www.java1234.com
 * @company 南通小锋网络科技有限公司
 * @create 2021-07-16 10:55
 */
@FeignClient("seata-account")
public interface AccountFeignService {

    /**
     * 账号扣钱
     * @param amount
     * @param userId
     * @return
     */
    @PostMapping("/account/decrease")
    public boolean decrease(@RequestParam("amount")Integer amount, @RequestParam("userId")Integer userId);

}

WebController

package com.java1234.controller;

import com.java1234.entity.Order;
import com.java1234.feign.AccountFeignService;
import com.java1234.feign.OrderFeignService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * web-rest接口
 * @author java1234_小锋
 * @site www.java1234.com
 * @company 南通小锋网络科技有限公司
 * @create 2021-07-15 16:32
 */
@RestController
public class WebController {

    @Autowired
    private OrderFeignService orderFeignService;

    @Autowired
    private AccountFeignService  accountFeignService;

    /**
     * 下单 1,创建订单 2,账户扣钱
     * @param order
     * @return
     */
    @PostMapping("/shopping")
    public boolean shopping(Order order){
        orderFeignService.createOrder(order); // 创建订单
        accountFeignService.decrease(order.getAmount(),order.getUserId()); // 账户扣钱
        return true;
    }


}

2.8 postman测试

首先启动Nacos服务注册中心:

项目启动:

Nacos控制台:

服务注册成功!

测试接口:http://localhost/shopping

接口测试OK:

订单表生成订单:

账户表id=1的jack账户成功扣减180元;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/415900.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

10 在线逻辑分析仪的使用

在线逻辑分析仪简介 传统的 FPGA 板级调试是将逻辑分析仪连接到 FPGA 的 IO 引脚上 &#xff0c;然后将内部信号引出至 IO 引脚&#xff0c;再进行板级调试&#xff0c;这种方法的缺点是我们需要一个逻辑分析仪&#xff0c;且还要在 PCB 中预留测试点。在线逻辑分析仪克服了以…

配电房轨道式巡检机器人方案

一、应用背景 在变电站、配电房、开关站等各种室内变配电场所内&#xff0c;由于变配电设备的数量众多、可能存在各类安全隐患&#xff0c;为了保证用电的安全可靠&#xff0c;都要进行日常巡检。 但目前配电房人工巡检方式有以下主要问题&#xff1a; 巡检工作量大、成本高 …

三、西瓜书——神经网络

一、神经元模型 在M-P神经网络模型中&#xff0c;神经元接 收到来自n个其他神经元传递过来的输入信号&#xff0c;这些输入信号通过带权重的连接(connection)进行传递&#xff0c;神经元接收到的总输入值将与神经元的阈值进行比较&#xff0c;然后通过“激活函数”(activation …

【数据结构】C语言实现二叉树的相关操作

树 定义 树&#xff08;Tree&#xff09;是 n (n > 0) 个结点的有限集 若 n 0&#xff0c;称为空树 若 n > 0&#xff0c;则它满足如下两个条件&#xff1a; 有且仅有一个特定的称为根&#xff08;Root&#xff09;的结点其余结点可分为 m(m>0) 个互不相交的有限…

第十三篇【传奇开心果系列】Python的文本和语音相互转换库技术点案例示例:Microsoft Azure的Face API开发人脸识别门禁系统经典案例

传奇开心果博文系列 系列博文目录Python的文本和语音相互转换库技术点案例示例系列 博文目录前言一、实现步骤和雏形示例代码二、扩展思路介绍三、活体检测深度解读和示例代码四、人脸注册和管理示例代码五、实时监控和报警示例代码六、多因素认证示例代码七、访客管理示例代码…

ES6 | (二)ES6 新特性(下) | 尚硅谷Web前端ES6教程

文章目录 &#x1f4da;迭代器&#x1f407;定义&#x1f407;工作原理&#x1f407;自定义遍历数据 &#x1f4da;生成器函数&#x1f407;声明和调用&#x1f407;生成器函数的参数传递&#x1f407;生成器函数案例 &#x1f4da;Promise&#x1f4da;Set&#x1f407;Set的定…

AI大预言模型——ChatGPT在地学、GIS、气象、农业、生态、环境应用

原文链接&#xff1a;AI大预言模型——ChatGPT在地学、GIS、气象、农业、生态、环境应用 一开启大模型 1 开启大模型 1)大模型的发展历程与最新功能 2)大模型的强大功能与应用场景 3)国内外经典大模型&#xff08;ChatGPT、LLaMA、Gemini、DALLE、Midjourney、Stable Diff…

【论文阅读】微纳米气泡技术作为CO2-EOR和CO2地质储存技术的新方向:综述

Micro and nanobubbles technologies as a new horizon for CO2-EOR and CO2 geological storage techniques: A review 微纳米气泡技术作为CO2-EOR和CO2地质储存技术的新方向&#xff1a;综述 期刊信息&#xff1a;Fuel 2023 期刊级别&#xff1a;EI检索 SCI升级版工程技术1区…

解释一下前端框架中的虚拟DOM(virtual DOM)和实际DOM(real DOM)之间的关系。

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

从win11切换到ubuntu20的第1天

我不想做双系统&#xff0c;反正win11也没有意思&#xff0c;打游戏直接去网吧&#xff0c;所以电脑直接重装了ubuntu20&#xff0c;为什么不是ubuntu22&#xff1f;因为版本太新&#xff0c;很多东西不支持。为什么不装ubuntu18&#xff1f;因为我电脑装完了之后不支持外界显示…

通过大语言模型理解运维故障:评估和总结

张圣林 南开大学软件学院副教授、博士生导师 第六届CCF国际AIOps挑战赛程序委员会主席 在ATC、WWW、VLDB、KDD、SIGMETRICS等国际会议和JSAC、TC、TSC等国际期刊发表高水平论文50余篇。主持国家自然科学基金项目2项&#xff0c;横向项目13项&#xff08;与华为、字节跳动、腾讯…

华为s5720s-28p-power-li-ac堆叠配置

叠物理约束&#xff1a; • 连线推荐示意图选用产品子系列中固定的一款设备做示例&#xff0c;与选择产品时指定型号的外观可能不同。示意图主要用于让用户了解相同子系列设备可以用作堆叠的端口的位置&#xff0c;以及使用不同的连线方式时如何连接设备上的端口。因此&#xf…

【Micropython教程】点亮第一个LED与流水灯

文章目录 前言MicroPython在线仿真GPIO的工作模式一、有哪些工作模式&#xff1f;1.1 GPIO的详细介绍1.2 GPIO的内部框图输入模式输出部分 一、machine.Pin类1.1 machine.Pin 类的构造对象1.2 machine.Pin 类的方法init方法value方法设置高低电平方法 二、延时函数 三、流水灯总…

2024年2月深度学习的论文推荐

我们这篇文章将推荐2月份发布的10篇深度学习的论文 Beyond A*: Better Planning with Transformers via Search Dynamics Bootstrapping. https://arxiv.org/abs/2402.14083 Searchformer是一个基于Transformer架构的人工智能模型&#xff0c;经过训练可以模拟A星寻路算法&a…

博途V18界面的各变量用途

在编程的时候会用到相关的变量包括&#xff1a; 1.在程序块中新建的“数据块” DB 。 在此建立的 变量数据块&#xff0c;它可以是自建在PLC数据类型的变量类型&#xff0c;也可以是各种标准的数据类型&#xff0c;且在DB数据块中的变量一般为全局变量&#xff0c;在整个项目…

nginx------------缓存功能 (六)

一、http 协议反向代理 &#xff08;一&#xff09;反向代理示例:缓存功能 缓存功能可以加速访问&#xff0c;如果没有缓存关闭后端服务器后&#xff0c;图片将无法访问&#xff0c;缓存功能默认关闭&#xff0c;需要开启。 ​ proxy_cache zone_name | off; 默认off #指明调…

[Tomcat] 控制台日志乱码,快速解决

启动tomcat之后&#xff0c;控制台打印的日志中出现了中文乱码的情况 解决方法 找到tomcat下的conf目录下的logging.properties文件&#xff0c;地址一般为&#xff1a;C:\apache-tomcat-9.0.17\conf 将logging.properties打开&#xff0c;将java.util.logging.ConsoleHandler…

向量数据库PGVECTOR,AI浪潮下崛起的新秀!

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#x1f4e3;&#x1f4e3;&#x1f4e3; 哈喽&#xff01;大家好&#xff0c;我是【IT邦德】&#xff0c;江湖人称jeames007&#xff0c;10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】&#xff01;&#x1f61c;&am…

Javaweb day7

Ajax 写法 &#xff08;比较落后&#xff09; 简化版&#xff1a;AXIOS 写法 简化 案例&#xff1a; 基础代码 写法

项目流程图

实现便利店自助付款项目 服务器&#xff1a; 1、并发服务器&#xff08;多进程、多线程、IO多路复用&#xff09; 2、SQL数据库的创建和使用&#xff08;增删改查&#xff09; 3、以模块化编写项目代码&#xff0c;按照不同模块编写.h/.c文件 客户端&#xff1a; 1、QT客户端界…