SpringBoot3.2.5整合Seata1.8.0详细教程

 更新时间:2026年03月17日 09:42:53   作者:BlueSea 每日coding  
本文详细介绍了SpringBoot3.2.5项目整合Seata1.8.0实现分布式事务的全过程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

在微服务架构中,分布式事务是一个无法回避的难题。Seata 作为一款开源的分布式事务解决方案,致力于提供高性能和简单易用的分布式事务服务。本文将通过一步步的教程,带你掌握如何在 Spring Boot 3.2.5 项目中整合 Seata 1.8.0,实现分布式事务控制。

环境准备

在开始整合之前,请确保你的开发环境满足以下要求:

  • JDK:17 或更高版本(Spring Boot 3.x 要求 JDK 17+)
  • Spring Boot:3.2.5
  • Seata:1.8.0
  • 注册中心:Nacos(本文使用 Nacos 作为注册中心和配置中心)
  • 数据库:MySQL 5.7+
  • 项目构建工具:Maven 3.6+

Seata 服务端部署

Seata 服务端(TC,即 Transaction Coordinator)是分布式事务的协调器,我们需要先部署好 Seata Server。

1. 下载 Seata Server

从 Seata 官方 GitHub Release 页面下载 seata-server-1.8.0 的压缩包:

wget https://github.com/seata/seata/releases/download/v1.8.0/seata-server-1.8.0.tar.gz
tar -zxvf seata-server-1.8.0.tar.gz

2. 配置 Seata Server

Seata 1.8.0 版本使用 application.yml 作为配置文件,位于 seata/conf 目录下。

2.1 配置注册中心和配置中心

修改 application.yml,设置使用 Nacos 作为注册中心和配置中心:

seata:
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      namespace: ""
      group: SEATA_GROUP
      username: "nacos"
      password: "nacos"
      data-id: seataServer.properties
  registry:
    type: nacos
    nacos:
      application: seata-server
      server-addr: 127.0.0.1:8848
      group: SEATA_GROUP
      namespace: ""
      cluster: default
      username: "nacos"
      password: "nacos"

2.2 配置存储模式(可选)

如果需要持久化事务日志,可以配置使用数据库存储。在 Nacos 配置中心创建 data-id 为 seataServer.properties 的配置,添加以下内容:

# 存储模式
store.mode=db

# 数据库配置
store.db.datasource=druid
store.db.dbType=mysql
store.db.driverClassName=com.mysql.cj.jdbc.Driver
store.db.url=jdbc:mysql://127.0.0.1:3306/seata_server?useUnicode=true&rewriteBatchedStatements=true
store.db.user=root
store.db.password=123456
store.db.minConn=5
store.db.maxConn=30
store.db.globalTable=global_table
store.db.branchTable=branch_table
store.db.lockTable=lock_table
store.db.queryLimit=100

3. 初始化数据库表

如果使用数据库模式,需要在 MySQL 中创建 Seata 服务端所需的表:

-- 创建数据库
CREATE DATABASE IF NOT EXISTS seata_server;

-- 建表脚本位于 seata/script/server/db/ 目录下
-- 执行 mysql.sql 文件
SOURCE /path/to/seata/script/server/db/mysql.sql;

4. 启动 Seata Server

执行启动脚本:

# Linux/Mac
sh ./bin/seata-server.sh

# Windows
.\bin\seata-server.bat

服务启动后,默认监听端口:7091(控制台)和 8091(服务端口)。访问 Nacos 控制台,如果看到 seata-server 服务注册成功,则表示部署完成。

Spring Boot 客户端整合

接下来,我们将创建两个 Spring Boot 微服务(订单服务和库存服务)来演示分布式事务。

1. 创建 Spring Boot 项目

使用 Spring Initializr 创建两个 Spring Boot 3.2.5 项目:

  • order-service(订单服务,端口 8081)
  • storage-service(库存服务,端口 8082)

2. 引入依赖

在每个服务的 pom.xml 中添加 Seata 依赖:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.2.5</version>
</parent>

<dependencies>
    <!-- Spring Boot Web -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- Spring Boot Data JPA -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <!-- MySQL Driver -->
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <scope>runtime</scope>
    </dependency>

    <!-- Seata Spring Boot Starter -->
    <dependency>
        <groupId>io.seata</groupId>
        <artifactId>seata-spring-boot-starter</artifactId>
        <version>1.8.0</version>
    </dependency>

    <!-- Nacos 注册中心客户端(Seata 注册需要) -->
    <dependency>
        <groupId>com.alibaba.nacos</groupId>
        <artifactId>nacos-client</artifactId>
        <version>2.2.3</version>
    </dependency>
</dependencies>

3. 客户端配置

在每个服务的 application.yml 中添加 Seata 配置:

server:
  port: 8081  # 订单服务端口

spring:
  application:
    name: order-service
  datasource:
    url: jdbc:mysql://localhost:3306/order_db?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: 123456
    driver-class-name: com.mysql.cj.jdbc.Driver

# Seata 配置
seata:
  enabled: true
  application-id: ${spring.application.name}
  tx-service-group: default_tx_group
  # 服务端分组映射
  service:
    vgroup-mapping:
      default_tx_group: default
  # 注册中心配置
  registry:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      namespace: ""
      group: SEATA_GROUP
      username: "nacos"
      password: "nacos"
  # 配置中心(可选)
  config:
    type: nacos
    nacos:
      server-addr: 127.0.0.1:8848
      namespace: ""
      group: SEATA_GROUP
      username: "nacos"
      password: "nacos"
      data-id: seataClient.properties
  # 数据源代理(自动开启)
  enable-auto-data-source-proxy: true
  # 使用 AT 模式
  data-source-proxy-mode: AT

4. 创建 undo_log 表

Seata AT 模式需要在每个业务数据库中创建 undo_log 表,用于记录事务回滚日志:

-- 注意:在 order_db 和 storage_db 中都执行
CREATE TABLE IF NOT EXISTS `undo_log`
(
    `id`            BIGINT(20)   NOT NULL AUTO_INCREMENT COMMENT 'increment id',
    `branch_id`     BIGINT(20)   NOT NULL COMMENT 'branch transaction id',
    `xid`           VARCHAR(100) NOT NULL COMMENT 'global transaction id',
    `context`       VARCHAR(128) NOT NULL COMMENT 'undo_log context,such as serialization',
    `rollback_info` LONGBLOB     NOT NULL COMMENT 'rollback info',
    `log_status`    INT(11)      NOT NULL COMMENT '0:normal status,1:defense status',
    `log_created`   DATETIME     NOT NULL COMMENT 'create datetime',
    `log_modified`  DATETIME     NOT NULL COMMENT 'modify datetime',
    PRIMARY KEY (`id`),
    UNIQUE KEY `ux_undo_log` (`xid`, `branch_id`)
) ENGINE = InnoDB
  AUTO_INCREMENT = 1
  DEFAULT CHARSET = utf8mb4 COMMENT ='AT transaction mode undo table';

5. 业务代码实现

5.1 库存服务 (Storage Service)

库存服务提供扣减库存的接口:

@RestController
@RequestMapping("/storage")
public class StorageController {

    @Autowired
    private StorageRepository storageRepository;

    @PostMapping("/deduct")
    public String deduct(@RequestParam Long productId, @RequestParam Integer count) {
        Storage storage = storageRepository.findByProductId(productId);
        if (storage.getCount() < count) {
            throw new RuntimeException("库存不足");
        }
        storage.setCount(storage.getCount() - count);
        storageRepository.save(storage);
        return "扣减成功";
    }
}

@Entity
public class Storage {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private Long productId;
    private Integer count;
    // getters and setters
}

5.2 订单服务 (Order Service)

订单服务创建订单并调用库存服务:

@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private OrderRepository orderRepository;

    @PostMapping("/create")
    @GlobalTransactional(name = "create-order", rollbackFor = Exception.class)
    public String createOrder(@RequestParam Long productId, 
                              @RequestParam Integer count,
                              @RequestParam BigDecimal amount) {
        // 1. 创建本地订单
        Order order = new Order();
        order.setProductId(productId);
        order.setCount(count);
        order.setAmount(amount);
        order.setStatus(0); // 待处理
        orderRepository.save(order);

        // 2. 远程调用库存服务扣减库存
        String url = "http://localhost:8082/storage/deduct?productId=" + productId + "&count=" + count;
        String result = restTemplate.postForObject(url, null, String.class);

        // 3. 更新订单状态
        order.setStatus(1); // 已完成
        orderRepository.save(order);

        return "订单创建成功";
    }
}

注意:@GlobalTransactional 注解是关键,它标识该方法需要开启全局事务。

6. 配置 RestTemplate

在订单服务中,需要配置 RestTemplate 以实现服务调用,并确保 Seata 的 XID 能够透传:

@Configuration
public class SeataRestTemplateConfig {

    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    /**
     * 配置 RestTemplate 拦截器,实现 XID 传递
     */
    @Bean
    public RestTemplate restTemplate(RestTemplate restTemplate) {
        restTemplate.setInterceptors(Collections.singletonList(new RestTemplateInterceptor()));
        return restTemplate;
    }

    /**
     * 自定义拦截器,将 Seata 的 XID 放入请求头
     */
    public static class RestTemplateInterceptor implements ClientHttpRequestInterceptor {
        @Override
        public ClientHttpResponse intercept(HttpRequest request, byte[] body, 
                                            ClientHttpRequestExecution execution) throws IOException {
            String xid = RootContext.getXID();
            if (StringUtils.isNotBlank(xid)) {
                request.getHeaders().add(RootContext.KEY_XID, xid);
            }
            return execution.execute(request, body);
        }
    }
}

测试分布式事务

1. 正常流程测试

请求订单创建接口:

curl "http://localhost:8081/order/create?productId=1&count=2&amount=100"

观察数据库:

  • 订单表新增一条状态为 1 的记录
  • 库存表对应商品库存减少 2

2. 异常回滚测试

修改库存服务,主动抛出异常:

@PostMapping("/deduct")
public String deduct(@RequestParam Long productId, @RequestParam Integer count) {
    Storage storage = storageRepository.findByProductId(productId);
    if (storage.getCount() < count) {
        throw new RuntimeException("库存不足");
    }
    storage.setCount(storage.getCount() - count);
    storageRepository.save(storage);
    
    // 模拟异常
    if (productId == 1) {
        throw new RuntimeException("模拟库存服务异常");
    }
    return "扣减成功";
}

再次请求订单创建接口,观察结果:

  • 订单表新增的记录状态为 0(说明未被更新)
  • 库存表数量未减少
  • undo_log 表中会记录回滚日志

常见问题及解决方案

1. 版本兼容性问题

Spring Boot 3.2.5 使用了 Jakarta EE 9+(javax 包名改为 jakarta),而 Seata 1.8.0 已经完全支持 Jakarta,无需额外配置。如果遇到类找不到的问题,检查是否有依赖引入了旧的 javax 包。

2. XID 传递失败

跨服务调用时,如果下游服务无法获取 XID,事务会失效。解决方案:

  • 使用支持 Seata 的微服务组件(如 Spring Cloud Alibaba)
  • 手动实现拦截器传递 XID(如上面的 RestTemplate 配置)

3. 数据源代理冲突

如果项目中同时使用 Druid 等连接池,需要确保 Seata 的数据源代理正确执行。Seata 的 seata-spring-boot-starter 会自动代理数据源,无需额外配置。

4. 注册中心连接失败

检查 Nacos 地址和端口是否正确,确保 Seata Server 已经成功注册到 Nacos。

总结

本文详细介绍了 Spring Boot 3.2.5 整合 Seata 1.8.0 的全过程,包括服务端部署、客户端配置、业务代码实现以及测试验证。Seata 的 AT 模式通过代理数据源和记录 undo_log,对业务代码无侵入,是分布式事务接入的首选方案。

在实际生产环境中,建议:

  • 使用数据库模式存储事务日志,保证数据持久化
  • 合理设置事务超时时间和重试策略
  • 做好监控和告警,及时发现事务异常

到此这篇关于SpringBoot3.2.5整合Seata1.8.0详细教程的文章就介绍到这了,更多相关SpringBoot整合Seata内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java实现窗口刷新的示例代码

    java实现窗口刷新的示例代码

    本文主要介绍了java实现窗口刷新的示例代码,通过重写paintComponent()方法和调用repaint()方法,可以实现窗口的即时刷新,具有一定的参考价值,感兴趣的可以了解一下
    2024-02-02
  • springboot中使用@NotNull注解无效解决方法

    springboot中使用@NotNull注解无效解决方法

    这篇文章主要给大家介绍了关于springboot中使用@NotNull注解无效的解决方法,进行参数校验的时候,加了@NotNull注解,@Validated注解和@Valid注解,但是参数校验的时候不生效,需要的朋友可以参考下
    2023-08-08
  • SpringBoot处理跨域请求的四种方法

    SpringBoot处理跨域请求的四种方法

    在现代Web应用中,由于安全性和隐私的考虑,浏览器限制了从一个域向另一个域发起的跨域HTTP请求,解决这个问题的一种常见方式是实现跨域资源共享(CORS),SpringBoot提供了多种方式来处理跨域请求,本文将介绍其中的几种方法,感兴趣的朋友可以参考下
    2023-12-12
  • java双端队列之ArrayDequeue原理讲解

    java双端队列之ArrayDequeue原理讲解

    这篇文章主要为大家介绍了java双端队列之ArrayDequeue原理讲解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-06-06
  • java 根据前端返回的字段名进行查询数据

    java 根据前端返回的字段名进行查询数据

    本文介绍了如何在Java中使用SpringDataJPA实现动态查询功能,以便根据前端传递的字段名动态构建查询语句,通过创建实体类、Repository接口、构建动态查询、在Service层和Controller中使用动态查询,实现了前后端分离架构中的灵活查询需求
    2024-11-11
  • Java多线程处理千万级数据更新操作

    Java多线程处理千万级数据更新操作

    这篇文章主要为大家详细介绍了Java如何通过多线程处理千万级数据更新操作,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-11-11
  • Java高性能缓存框架之Caffeine详解

    Java高性能缓存框架之Caffeine详解

    这篇文章主要介绍了Java高性能缓存框架之Caffeine详解,Caffeine是一个基于Java8的高性能缓存框架,号称趋于完美,Caffeine受启发于Guava Cache的API,使用API和Guava是一致的,需要的朋友可以参考下
    2023-12-12
  • 详解Java中异步转同步的六种方法

    详解Java中异步转同步的六种方法

    针对应用中异步调用,能不能像同步调用一样立刻获取到命令的执行结果,如何实现异步转同步?不要担心,本文就来为大家详细讲讲Java中异步转同步的六种方法,感兴趣的可以了解一下
    2022-06-06
  • maven+阿里云创建国内镜像的中央仓库(亲测可用)

    maven+阿里云创建国内镜像的中央仓库(亲测可用)

    本篇文章主要介绍了maven+阿里云创建国内镜像的中央仓库(亲测可用),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-12-12
  • 关于Nacos配置管理的统一配置管理、自动刷新详解

    关于Nacos配置管理的统一配置管理、自动刷新详解

    这篇文章主要介绍了关于Nacos配置管理的统一配置管理、自动刷新详解,Nacos是阿里的一个开源产品,是针对微服务架构中的服务发现、配置管理、服务治理的综合型解决方案,需要的朋友可以参考下
    2023-05-05

最新评论