1.pom.xml加入seata的依赖:
<!--分布式事务 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-seata</artifactId>
<!-- seata里面默认是0.7.0版本,排除默认版本;根据自己seata服务版本导入对应的版本,
我现在的版本是0.9.0,因此重新导入0.9.0版本的jar-->
<exclusions>
<exclusion>
<groupId>io.seata</groupId>
<artifactId>seata-all</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 因为本地是seata-server-0.9.0,所以导入seata版本为0.9.0-->
<dependency>
<groupId>io.seata</groupId>
<artifactId>seata-all</artifactId>
<version>0.9.0</version>
</dependency>
2.yml配置文件中配置事务分组,事务分组名称必须和seata/conf/file.config文件中vgroup_mapping的key保持一致
spring:
cloud:
alibaba:
seata:
tx-service-group: default-test #事务分组,必须与seata/conf/file.config文件中service的vgroup_mapping的key保持一致
3.将seata/conf/file.config和registry.conf拷贝到resources目录下
3.1 file.config文件修改
#修改事务分组名称,key必须和yml配置文件中的tx-service-group保持一致
第31行:vgroup_mapping.my_test_tx_group = "default" 修改为 vgroup_mapping.default-test = "default"
#调整数据存储方式为db数据库
第57行:mode="file" 修改为 mode = "db"
3.2 registry.conf文件修改
修改配置文件registry.conf中注册中心修改nacos注册中心
调整registry节点的注册中心
第3行:type="file" 修改为 type = "nacos" # 使用nacos注册中心作为注册中心
调整nacos配置信息
第6行:serverAddr = "localhost" 修改为 serverAddr = "localhost:8848" #nacos的地址
4.创建seata数据源代理类
package com.itsource.config;
import com.alibaba.druid.pool.DruidDataSource;
import io.seata.rm.datasource.DataSourceProxy;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.transaction.SpringManagedTransactionFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import javax.sql.DataSource;
//使用seata对DataSource进行代理
@Configuration
public class DataSourceProxyConfig {
//mapper.xml路径
@Value("${mybatis.mapper-locations}")
private String mapperLocations;
//手动配置bean
@Bean
@ConfigurationProperties("spring.datasource")
public DataSource druidDataSource(){
return new DruidDataSource();
}
@Bean
public SqlSessionFactory sessionFactory(DataSourceProxy dataSourceProxy) throws Exception {
SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean();
sessionFactoryBean.setDataSource(dataSourceProxy);
sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocations));
//事务管理工厂
sessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory());
return sessionFactoryBean.getObject();
}
@Bean
public DataSourceProxy dataSource() {
return new DataSourceProxy(druidDataSource());
}
}
5. springboot启动类上排除数据源自动配置:exclude = DataSourceAutoConfiguration.class
package com.itsource;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)//排除DataSource自动创建,因为上面已经手动配置了DataSource
public class UserServerApplication1010 {
/**
* 服务启动入口类
* @param args
*/
public static void main(String[] args) {
SpringApplication.run(UserServerApplication1010.class);
}
}
6. 服务调用方@GlobalTransactional标签开启全局事务,只要在调用方开启即可,被调用方无需使用全局事务标签
package com.itsource.service.impl;
import com.itsource.domain.Order;
import com.itsource.domain.User;
import com.itsource.feign.clients.UserClient;
import com.itsource.mapper.OrderMapper;
import com.itsource.service.IOrderService;
import io.seata.core.context.RootContext;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Transactional //本地事务管理
@Service
public class OrderServiceImpl implements IOrderService {
@Autowired
OrderMapper orderMapper;
@Autowired
UserClient userClient;
@Override
public int insert(Order order) {
return orderMapper.insert(order);
}
//创建订单并且远程调用User接口生成User用户
@GlobalTransactional //开启全局事务,全局事务只要在调用方开启全局事务即可,第三方服务不要使用全局事务注解@GlobalTransactional标签
@Override
public void create() {
System.out.println("Seata全局事务id=================>{}" + RootContext.getXID());
Order order = new Order();
order.setIntro("新增成功");
//1.保存订单
insert(order);
//2.远程调用User接口
User user = new User();
user.setUsername("新增");
user.setIntro("用户新增成功");
userClient.save(user);
int i = 2/0; //除零报错,全局事务回滚
}
}
7 特别注意:
集成seata时,注意sentinel必须使用alibaba的jar,不用使用springcloud的sentinel,
否则会提示类找不到com.alibaba.cloud.sentinel.feign.SentinelFeign,
因为spring-cloud-alibaba-seata-xxx.jar中使用了spring-cloud-alibaba-sentinel-xxx.jar中的SentinelFeign类
<!-- sentinel 服务限流 -->
<!--<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>