分布式事务

2.启动eureka注册服务
2.1.创建模块
2.2.添加依赖:
2.3.yml配置:
2.4.启动类添加注解@EnableEurekaServer
3.创建订单父级项目
3.1.创建一个父级项目,统一管理订单/账户/库存项目的依赖
3.2.pom文件粘贴:
4.创建子项目账目
4.1.创建子项目
4.2.修改依赖,parent继承父级
4.3.yml配置
4.4.布置项目中的类:
5.创建库存模块:
5.1.创建项目
5.2.pom.xml
5.3.yml配置
5.4.项目中的类:
6.创建订单子项目
6.1.创建项目
6.2.pom.xml
6.3.yml配置
6.4.项目中的类:
7.配置全局唯一id发号器
7.1下载项目


老师的对应CSDN
https://wanght.blog.csdn.net/article/details/107596037

2.启动eureka注册服务
2.1.创建模块

2.2.添加依赖:

2.3.yml配置:
spring:
application:
name: eureka-server
server:
port: 8761
eureka:
server:
#关闭保护模式
enable-self-preservation: false
client:
# 对单台服务器,不注册不拉取
register-with-eureka: false
fetch-registry: false
2.4.启动类添加注解@EnableEurekaServer
配置完,启动服务,并访问端口
效果:

3.创建订单父级项目
3.1.创建一个父级项目,统一管理订单/账户/库存项目的依赖

3.2.pom文件粘贴:

修改版本号:

<?xml version="1.0" encoding="UTF-8"?>


4.0.0

org.springframework.boot
spring-boot-starter-parent
2.3.12.RELEASE


cn.tedu
order-parent
1.0-SNAPSHOT
pom
order-parent

<properties>
    <mybatis-plus.version>3.3.2</mybatis-plus.version>
    <druid-spring-boot-starter.version>1.1.23</druid-spring-boot-starter.version>
    <seata.version>1.3.0</seata.version>
    <spring-cloud-alibaba-seata.version>2.0.0.RELEASE</spring-cloud-alibaba-seata.version>
    <spring-cloud.version>Hoxton.SR11</spring-cloud.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>

    <dependency>
        <groupId>com.baomidou</groupId>
        <artifactId>mybatis-plus-boot-starter</artifactId>
        <version>${mybatis-plus.version}</version>
    </dependency>

    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>${druid-spring-boot-starter.version}</version>
    </dependency>
    <!--<dependency>-->
    <!--  <groupId>com.alibaba.cloud</groupId>-->
    <!--  <artifactId>spring-cloud-alibaba-seata</artifactId>-->
    <!--  <version>${spring-cloud-alibaba-seata.version}</version>-->
    <!--  <exclusions>-->
    <!--    <exclusion>-->
    <!--      <artifactId>seata-all</artifactId>-->
    <!--      <groupId>io.seata</groupId>-->
    <!--    </exclusion>-->
    <!--  </exclusions>-->
    <!--</dependency>-->
    <!--<dependency>-->
    <!--  <groupId>io.seata</groupId>-->
    <!--  <artifactId>seata-all</artifactId>-->
    <!--  <version>${seata.version}</version>-->
    <!--</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>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>${spring-cloud.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>
父项目的src没有用,删掉

4.创建子项目账目
右键点order-parent,新建模块,注意父级,别创建错误
4.1.创建子项目

不用加依赖,修改一下spring版本,下一步,注意路径正确:

4.2.修改依赖,parent继承父级

<?xml version="1.0" encoding="UTF-8"?>



order-parent
cn.tedu
1.0-SNAPSHOT

<modelVersion>4.0.0</modelVersion>
<artifactId>account</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>account</name>
<description>Demo project for Spring Boot</description>

4.3.yml配置
spring:
application:
name: account
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost/seata_account?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
username: root
password: root

8081 account

8082 storage

8083 order

server:
port: 8081
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
instance:
# 注册ip
prefer-ip-address: true
# 显示ip
instance-id: s p r i n g . c l o u d . c l i e n t . i p − a d d r e s s : {spring.cloud.client.ip-address}: spring.cloud.client.ipaddress:{spring.application.name}😒{server.port}

mybatis-plus:
mapper-locations: classpath:/mapper/*.xml
configuration:
# 驼峰命名
map-underscore-to-camel-case: true
type-aliases-package: cn.tedu.account.entity

打开sql语句执行日志

logging:
level:
cn.tedu.account.mapper: debug

#bootstrap.yml

选择网卡

spring:
cloud:
inetutils:
preferred-networks:
# 本机ip
- 172.88.13…+

4.4.布置项目中的类:

Account :
package cn.tedu.account.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.math.BigDecimal;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Account {
private Long id;
private Long userId;
private BigDecimal total; //总金额
private BigDecimal used; //已使用
private BigDecimal residue; //可用
private BigDecimal frozen; //冻结
}
AccountMapper :
package cn.tedu.account.mapper;

import cn.tedu.account.entity.Account;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

import java.math.BigDecimal;

public interface AccountMapper extends BaseMapper {
void decrease(Long userId, BigDecimal money);
}
AccountMapper.xml:
用File创建文件的时候,用/表示文件目录

<?xml version="1.0" encoding="UTF-8" ?> UPDATE account SET residue = residue - #{money},used = used + #{money} where user_id = #{userId}; 启动类添加包扫描: // 扫描mapper所在的包,会自动创建代理对象 @MapperScan("cn.tedu.account.mapper")

package cn.tedu.account.service;

import java.math.BigDecimal;

public interface AccountService {
void decrease(Long userId, BigDecimal money);
}

package cn.tedu.account.service;

import cn.tedu.account.mapper.AccountMapper;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountMapper accountMapper;
@Override
public void decrease(Long userId, BigDecimal money) {
accountMapper.decrease(userId,money);
}
}

package cn.tedu.account.controller;

import cn.tedu.account.service.AccountService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;

@RestController
public class AccountController {
@Autowired
private AccountService accountService;
@GetMapping("/decrease") // /decrease?useId=1&money=100
public String decrease(Long useId, BigDecimal money){
accountService.decrease(useId, money);
return “账户扣减成功”;
}
}
效果:

5.创建库存模块:
5.1.创建项目

依赖改一下spring版本,不用加其他依赖,注意路径:

5.2.pom.xml

<?xml version="1.0" encoding="UTF-8"?>



order-parent
cn.tedu
1.0-SNAPSHOT

<modelVersion>4.0.0</modelVersion>
<artifactId>storage</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>storage</name>
<description>Demo project for Spring Boot</description>
5.3.yml配置 yml配置文件,直接复制account的两个yml,改一下(将account改为storage,四处记得改表名,改一下端口号) spring: application: name: storage datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost/seata_storage?useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8 username: root password: root # 8081 account # 8082 storage # 8083 order server: port: 8082 eureka: client: service-url: defaultZone: http://localhost:8761/eureka instance: # 注册ip prefer-ip-address: true # 显示ip instance-id: ${spring.cloud.client.ip-address}:${spring.application.name}:${server.port}

mybatis-plus:
mapper-locations: classpath:/mapper/*.xml
configuration:
# 驼峰命名
map-underscore-to-camel-case: true
type-aliases-package: cn.tedu.storage.entity

打开sql语句执行日志

logging:
level:
cn.tedu.storage.mapper: debug

#bootstrap.yml

选择网卡

spring:
cloud:
inetutils:
preferred-networks:
# 本机ip
- 172.88.13…+

5.4.项目中的类:

package cn.tedu.storage.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Storage {
private Long id;
private Long productid;
private Integer total;
private Integer used;
private Integer residue;
private Integer frozen;

}

package cn.tedu.storage.mapper;

import cn.tedu.storage.entity.Storage;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

public interface StorageMapper extends BaseMapper {
void decrease(Long productId,Integer count);
}

package cn.tedu.storage.service;

public interface StorageService {
void decrease(Long productId,Integer count);
}

package cn.tedu.storage.service;

import cn.tedu.storage.mapper.StorageMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class StorageServiceImpl implements StorageService {
@Autowired
private StorageMapper storageMapper;
@Override
public void decrease(Long productId, Integer count) {
storageMapper.decrease(productId, count);
}
}
启动类加注解
@MapperScan(“cn.tedu.storage.mapper”)
StorageMapper.xml:

<?xml version="1.0" encoding="UTF-8" ?> UPDATE storage SET used = used + #{count},residue = residue - #{count} WHERE product_id = #{productId}

package cn.tedu.storage.controller;

import cn.tedu.storage.service.StorageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class StorageController {
@Autowired
private StorageService storageService;
@GetMapping("/decrease") // /decrease?productId=1&count=10
public String decrease(Long productId, Integer count){
storageService.decrease(productId, count);
return “减少商品库存成功”;
}
}
效果:

6.创建订单子项目
6.1.创建项目

依赖改一下spring版本,不用加其他依赖,注意路径:

6.2.pom.xml

<?xml version="1.0" encoding="UTF-8"?>



order-parent
cn.tedu
1.0-SNAPSHOT

<modelVersion>4.0.0</modelVersion>
<artifactId>order</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>order</name>
<description>Demo project for Spring Boot</description>
6.3.yml配置 重复5.3的操作,yml配置文件,直接复制account的两个yml,改一下(将account改为order,四处记得改表名,改一下端口号)

6.4.项目中的类:

package cn.tedu.order.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.math.BigDecimal;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Order {
private Long id;
private Long userId;
private Long productId;
private Integer count;
private BigDecimal money;
private Integer status;
}

package cn.tedu.order.mapper;

import cn.tedu.order.entity.Order;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

public interface OrderMapper extends BaseMapper {
void create(Order order);
}
OrderMapper.xml
sql语句中,字段必须加反引号,因为在mapper里边order是关键字,所以要加反引号,后边括号里边的字段非关键字,可加可不加

<?xml version="1.0" encoding="UTF-8" ?> INSERT INTO `order` (`id`,`user_id`,`product_id`,`count`,`money`,`status`) VALUES(#{id}, #{userId}, #{productId}, #{count}, #{money},1);

package cn.tedu.order.service;

import cn.tedu.order.entity.Order;

public interface OrderService {
void create(Order order);
}

package cn.tedu.order.service;

import cn.tedu.order.entity.Order;
import cn.tedu.order.mapper.OrderMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Random;

@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderMapper orderMapper;
@Override
public void create(Order order) {
// TODO:远程调用发号器生成订单id

    //临时随机生成一个id,添加发号器后这行代码删除
    // Math.abs()生成绝对值的方法
    Long orderId= Math.abs(new Random().nextLong());
    order.setId(orderId);
    orderMapper.create(order);

    //TODO: 远程调用库存减少商品库存
    //TODO: 远程调用账户扣减账户金额
}

}

package cn.tedu.order.controller;

import cn.tedu.order.entity.Order;
import cn.tedu.order.service.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class OrderController {
@Autowired
private OrderService orderService;
@GetMapping("/create") // /create?userId=1&productId=1&count=10&money=100
public String create(Order order){
orderService.create(order);
return “创建订单成功”;
}
}
启动类加注解:
@MapperScan(“cn.tedu.order.mapper”)
效果:

7.配置全局唯一id发号器
分布式系统中,产生唯一流水号的服务系统俗称发号器。

有很多发号器开源项目,这里使用 EasyIdGenerator,具体项目信息请访问:
https://github.com/lookingatstarts/easyIdGenerator

项目使用非常简单,将项目下载下来稍作配置即可。

7.1下载项目
访问 https://github.com/lookingatstarts/easyIdGenerator ,下载发号器项目。

将文件解压到项目下:

7.2.导入 Module
在Maven工具窗口中点击添加按钮,选择发号器项目的 pom.xml 文件导入该项目:
注意: 如果右侧没有Maven工具标签,请按两下shift键,然后查找 “add maven projects” 就可以找到这个工具。

7.3.配置
pom.xml
修改springboot版本

发号器向 eureka 进行注册,以便其它服务发现它。
在pom.xml 中添加 Spring Cloud Eureka Client 依赖:

<?xml version="1.0" encoding="UTF-8"?>


4.0.0

org.springframework.boot
spring-boot-starter-parent
2.3.12.RELEASE

<groupId>com.easy.id</groupId>
<artifactId>easy-id-generator</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <maven.compiler.target>1.8</maven.compiler.target>
    <maven.compiler.source>1.8</maven.compiler.source>
    <junit.version>4.12</junit.version>
    <mysql.connector.version>8.0.16</mysql.connector.version>
    <com.alibaba.fastjson.version>1.2.62</com.alibaba.fastjson.version>
    <lombok.version>1.18.8</lombok.version>
    <curator.version>2.6.0</curator.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>${lombok.version}</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>com.zaxxer</groupId>
        <artifactId>HikariCP</artifactId>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>${mysql.connector.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>fastjson</artifactId>
        <version>${com.alibaba.fastjson.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.curator</groupId>
        <artifactId>curator-recipes</artifactId>
        <version>${curator.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>

</dependencies>
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Hoxton.SR11</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
application.yml 配置使用数据库来生成自增id 向eureka进行注册 server: port: 9090

easy-id-generator:
snowflake:
enable: false
zk:
connection-string: 127.0.0.1:2181,127.0.0.1:2182,127.0.0.1:2183
load-worker-id-from-file-when-zk-down: true # 当zk不可访问时,从本地文件中读取之前备份的workerId
segment:
enable: true
db-list: “seata_order”
fetch-segment-retry-times: 3 # 从数据库获取号段失败重试次数

spring:
application:
name: easy-id-generator
eureka:
client:
service-url:
defaultZone: http://localhost:8761/eureka
instance:
prefer-ip-address: true

bootstrap.yml

选择网卡

spring:
cloud:
inetutils:
preferred-networks:
- 172.88.13…+
seata_order.properties 数据库配置
在 resources 目录下新建配置文件 seata_order.properties,配置 seata_order 数据库的连接信息。
jdbcUrl=jdbc:mysql://localhost:3306/seata_order?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=GMT%2B8
driverClassName=com.mysql.cj.jdbc.Driver
dataSource.user=root
dataSource.password=root
dataSource.cachePrepStmts=true
dataSource.prepStmtCacheSize=250
dataSource.prepStmtCacheSqlLimit=2048

数据表
在 db-init 项目的 order.sql 中已经创建了数据表,并插入了一个名为 order_business 的自增id条目。
项目的 schema.sql 中为示例数据表。

7.4.启动项目并访问测试
查看 eureka 中的注册信息

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值