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

news2024/11/17 21:41:57

锋哥原创的分布式事务框架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元;

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

记录工作中遇见问题、学习项

1、判空操作 Demo demo Optional .ofNullable(demoService.getById(id)) .orElseThrow(() -> new ServiceException("不存在id为" id "的数据")); 2、SQL方面 1、group by : GROUP BY 子句必须放在 WHERE 子句中的条件之后&#…

网络:IPv6

1、由于IPv4地址资源枯竭&#xff0c;所以产生了IPV6。 版本长度地址数量IPv432 bit4 294 967 296IPv6128 bit340 282 366 920 938 463 374 607 431 768 211 456 2、IPv6的基本报头在IPv4报头基础上&#xff0c;增加了流标签域&#xff0c;去除了一些冗余字段&#xff0c;使报…

Apache SeaTunnel 及 Web 功能部署指南(小白版)

在大数据处理领域&#xff0c;Apache SeaTunnel 已成为一款备受青睐的开源数据集成平台&#xff0c;它不仅可以基于Apache Spark和Flink&#xff0c;而且还有社区单独开发专属数据集成的Zeta引擎&#xff0c;提供了强大的数据处理能力。随着SeaTunnel Web的推出&#xff0c;用户…

Python异步IO库之uvloop使用详解

概要 在Python中,异步编程已经成为处理高并发和IO密集型任务的主要方式之一。而uvloop库则是一个专门针对异步IO操作进行优化的库,它能够显著提高异步程序的性能。本文将深入探讨uvloop库的使用方法、功能特性以及如何利用它来加速异步IO编程。 什么是uvloop库? uvloop是一…

探讨:围绕 props 阐述 React 通信

在 ✓ &#x1f1e8;&#x1f1f3; 开篇&#xff1a;通过 state 阐述 React 渲染 中&#xff0c;以 setInterval 为例&#xff0c;梳理了 React 渲染的相关内容。 &#x1f4e2; 本篇会 ✓ &#x1f1e8;&#x1f1f3; 围绕 props 阐述 React 通信 props React 组件使用 pro…

存储xss实现获取cookie(本地实战)

实战更能体验收获&#xff01;&#xff01;&#xff01; 环境准备&#xff1a; 1.phpstudy 2.dvwa靶场 实战 首先我们在phpstudy指定的localhost网站目录下编写一个xss.php文件&#xff0c;内容如下&#xff1a; <?php $cookie $_GET[cookie]; $ip getenv (REMOTE_…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的活体人脸检测系统(Python+PySide6界面+训练代码)

摘要&#xff1a;本篇博客详细讲述了如何利用深度学习构建一个活体人脸检测系统&#xff0c;并且提供了完整的实现代码。该系统基于强大的YOLOv8算法&#xff0c;并进行了与前代算法YOLOv7、YOLOv6、YOLOv5的细致对比&#xff0c;展示了其在图像、视频、实时视频流和批量文件处…

找出异常点 python

统计学方法 zscore 原理&#xff1a; Z-score 基于正态分布理论&#xff0c;它量化了数据点距离数据集平均值的相对标准偏差。 通常&#xff0c;如果 Z-score 的绝对值超过某个阈值&#xff08;如3或更大&#xff09;&#xff0c;该数据点就被认为是异常值。这是因为正态分布下…

【Spring】模拟 Spring 框架

Spring IoC 容器的实现原理&#xff1a;工厂模式 解析XML 反射机制 我们给自己的框架起名为&#xff1a;mySpring&#xff08;我的春天&#xff09; 一、创建 mySpring 模块 引入dom4j 和 jaxen 的依赖&#xff0c;因为要使用它解析XML文件&#xff0c;还有 junit 依赖 &l…

【MATLAB】SVMD_ MFE_SVM_LSTM 神经网络时序预测算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 SVMD_MFE_SVM_LSTM神经网络时序预测算法结合了单变量分解&#xff08;SVMD&#xff09;、多尺度特征提取&#xff08;MFE&#xff09;、聚类后展开支持向量机&#xff08;SVM&#xff09;…

Ethernet/IP转CC-Link IEFB协议网关

产品功能 1 YC-EIP-CCLKIE工业级EtherNet/IP 网关 2 CC-Link IEFB转 EtherNet/IP 3支持多个CC-Link IEFB节点 4 即插即用 无需编程 轻松组态 ,即实现数据交互 5导轨安装 支持提供EDS文件 6 EtherNET/IP与CC-Link IEFB互转数据透明传输可接入PLC组态 支持CodeSys/支持欧姆…

xss.haozi.me靶场练习

靶场地址alert(1) 1、第一关 输入在文本框里面&#xff0c;我们闭合前面的标签&#xff0c;中间的内容我们就可以随意写了 2、第二关 逃逸value的属性即可&#xff0c;这里使用点击事件触发xss 3、第三关 看代码&#xff0c;使用了正则表达式&#xff0c;去掉了所有的括号字…

【MATLAB】MVMD_ MFE_SVM_LSTM 神经网络时序预测算法

有意向获取代码&#xff0c;请转文末观看代码获取方式~也可转原文链接获取~ 1 基本定义 MVMD_MFE_SVM_LSTM神经网络时序预测算法结合了多变量多尺度分解&#xff08;MVMD&#xff09;、多尺度特征提取&#xff08;MFE&#xff09;、支持向量机&#xff08;SVM&#xff09;和长…

Vueuse:打造高效的 Vue.js 开发利器

Vueuse&#xff1a;打造高效的 Vue.js 开发利器 Vueuse 是一个功能强大的 Vue.js 生态系统工具库&#xff0c;它提供了一系列的可重用的 Vue 组件和函数&#xff0c;帮助开发者更轻松地构建复杂的应用程序。本文将介绍 Vueuse 的主要特点和用法&#xff0c;以及它在 Vue.js 开发…

JS总览-JS高级程序设计4-学习笔记

JS简史 1995年 JS 问世&#xff0c;彼时其主要任务是替代服务器端语言处理输入验证 1995年网景公司的 Brendan Eich 开发了一个脚注Live Script的脚步语言&#xff0c;后来网景公司与 Sun 公司结盟&#xff0c;更名 Live Script 为 Java Script 由于微软发布 IE3 时包含了自己…

【Linux】基础篇-Linux四种环境搭建的方式(详细安装说明步骤,搭载下载安装地址)

目录 1. 使用虚拟机&#xff08;推荐VMware&#xff09;centos 7版本 1.1VMware虚拟机下载 1.2VMware 安装 1.3centos-7 清华大学镜像下载 1.4 centos-7 清华大学镜像导入虚拟机VMware 2.使用虚拟机ubuntu 20.04版本 2.1虚拟机下载同上 2.2虚拟机安装同上 2.3ubunt…

selenium-激活pycharm,以及在pycharm中使用selenium时标红报错问题处理

激活pycharm&#xff1a;http://idea.955code.com/ 01 pycharm中导入selenium报错 现象: pycharm中输入from selenium import webdriver, selenium标红 原因1: pycharm使用的虚拟环境中没有安装selenium&#xff1a; 解决方法: 在pycharm中通过设置或terminal面板重新安装s…

KubeEdge 边缘计算

文章目录 1.KubeEdge2.KubeEdge 特点3.KubeEdge 组成4.KubeEdge 架构 KubeEdge # KubeEdgehttps://iothub.org.cn/docs/kubeedge/ https://iothub.org.cn/docs/kubeedge/kubeedge-summary/1.KubeEdge KubeEdge 是一个开源的系统&#xff0c;可将本机容器化应用编排和管理扩展…

最新版阿里云Linux CentOS7 ecs-user用户安装Mysql8详细教程(超简单)

经过两天的踩坑后&#xff0c;终于成功安装&#xff0c;并找到了最快捷的安装方式。接下来就由我来给大家介绍不踩坑安装大法&#xff01; 一、下载Mysql 首先前往Mysql官网下载 MySQL官方下载地址 第一步&#xff0c;选择安装包&#xff0c;这是最关键的一步&#xff0c;选错安…

弹窗内容由后端返回,如何让点击按钮的事件交由前端控制?

一、场景 背景&#xff1a;因为系统里经常有新活动或者公告需要通知所有用户&#xff0c;希望前端维护的这个弹窗里的内容可以由后端接口返回。这样就不需要每次上新活动的时候&#xff0c;前端项目都发版了。因此&#xff0c;前端维护了这个弹窗和它的关闭事件&#xff0c;至…