當前位置:
首頁 > 知識 > springboot+atomikos 分散式事務處理示例

springboot+atomikos 分散式事務處理示例

一、atomikos介紹:

Atomikos TransactionsEssentials 是一個為Java平台提供增值服務的並且開源類事務管理器,以下是包括在這個開源版本中的一些功能:

  • 全面崩潰 / 重啟恢復
  • 兼容標準的SUN公司JTA API
  • 嵌套事務
  • 為XA和非XA提供內置的JDBC適配器

Atomikos TransactionsEssentials是一個非常快速的嵌入式事務管理器,這就意味著,您不需要另外啟動一個單獨的事務管理器進程(不要查找任何的bin文件夾)。Atomikos TransactionsEssentials 是一個可靠的庫,可以加入到您的Java應用程序,也就是說為了使用這個產品,您只需添加一些jar文件到您的應用程序或者應用程序伺服器。

二、pom.xml文件配置:

1、添加atomikos依賴,同時需要加上springboot jdbc的依賴:

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-jdbc -->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-jdbc</artifactId>

<version>${spring.boot.version}</version>

</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-jta-atomikos -->

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-jta-atomikos</artifactId>

<version>${spring.boot.version}</version>

</dependency>

2、添加需要的資料庫連接池依賴,此處使用druid:

<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->

<dependency>

<groupId>com.alibaba</groupId>

<artifactId>druid</artifactId>

<version>${druid.version}</version>

</dependency>

<dependency>

<groupId>com.alibaba</groupId>

<artifactId>druid-spring-boot-starter</artifactId>

<version>1.1.1</version>

</dependency>

三、yum配置:

spring:

profiles:

active:

- test

datasource:

type: com.alibaba.druid.pool.xa.DruidXADataSource

druid:

# WebStatFilter配置,說明請參考Druid Wiki,配置_配置WebStatFilter

web-stat-filter:

enabled: true

urlPattern: /*

exclusions: /druid/*,*.js,*.gif,*.jpg,*.png,*.css,*.ico

sessionStatMaxCount:

sessionStatEnable:

principalSessionName: USER_SESSION

principalCookieName: USER_COOKIE

profileEnable: true

# StatViewServlet配置,說明請參考Druid Wiki,配置_StatViewServlet配置

stat-view-servlet:

enabled: true

urlPattern: /druid/*

resetEnable: false

loginUsername: admin

loginPassword: 123456

allow: 127.0.0.1

deny:

# Spring監控配置,說明請參考Druid Github Wiki,配置_Druid和Spring關聯監控配置

# Spring監控AOP切入點,如x.y.z.service.*,配置多個英文逗號分隔

aop-patterns:

- com.freeager.springboot.atomikos.*.service.**

database1:

name: DataSource1

url: jdbc:mysql://localhost/test

username: root

password: 123567

# 下面為連接池的補充設置,應用到上面所有數據源中

# 初始化大小,最小,最大

initialSize: 5

minIdle: 5

maxActive: 20

# 配置獲取連接等待超時的時間

maxWait: 60000

# 配置間隔多久才進行一次檢測,檢測需要關閉的空閑連接,單位是毫秒

timeBetweenEvictionRunsMillis: 60000

# 配置一個連接在池中最小生存的時間,單位是毫秒

minEvictableIdleTimeMillis: 30

validationQuery: SELECT user()

validationQueryTimeout: 10000

testWhileIdle: true

testOnBorrow: false

testOnReturn: false

# 打開PSCache,並且指定每個連接上PSCache的大小

poolPreparedStatements: true

maxPoolPreparedStatementPerConnectionSize: 20

filters: stat,wall

# 通過connectProperties屬性來打開mergeSql功能;慢SQL記錄

connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000

# 合併多個DruidDataSource的監控數據

useGlobalDataSourceStat: true

database2:

name: DataSource2

url: jdbc:mysql://localhost/mytest

username: root

password: 123567

# 下面為連接池的補充設置,應用到上面所有數據源中

# 初始化大小,最小,最大

initialSize: 5

minIdle: 5

maxActive: 20

# 配置獲取連接等待超時的時間

maxWait: 60000

# 配置間隔多久才進行一次檢測,檢測需要關閉的空閑連接,單位是毫秒

timeBetweenEvictionRunsMillis: 60000

# 配置一個連接在池中最小生存的時間,單位是毫秒

minEvictableIdleTimeMillis: 30

validationQuery: SELECT user()

validationQueryTimeout: 10000

testWhileIdle: true

testOnBorrow: false

testOnReturn: false

# 打開PSCache,並且指定每個連接上PSCache的大小

poolPreparedStatements: true

maxPoolPreparedStatementPerConnectionSize: 20

filters: stat,wall

# 通過connectProperties屬性來打開mergeSql功能;慢SQL記錄

connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000

# 合併多個DruidDataSource的監控數據

useGlobalDataSourceStat: true

#jta相關參數配置

jta:

log-dir: classpath:tx-logs

transaction-manager-id: txManager

四、配置代碼:

1、數據源:

@Configuration

public class DataSourceConfig {

@Bean(name = "DataSource1")

@Primary

@Autowired

public DataSource systemDataSource(Environment env) {

AtomikosDataSourceBean ds = new AtomikosDataSourceBean();

Properties prop = build(env, "spring.datasource.druid.database1.");

ds.setXaDataSourceClassName("com.alibaba.druid.pool.xa.DruidXADataSource");

ds.setUniqueResourceName("DataSource1");

ds.setPoolSize(5);

ds.setXaProperties(prop);

return ds;

}

@Autowired

@Bean(name = "DataSource2")

public DataSource businessDataSource(Environment env) {

AtomikosDataSourceBean ds = new AtomikosDataSourceBean();

Properties prop = build(env, "spring.datasource.druid.database2.");

ds.setXaDataSourceClassName("com.alibaba.druid.pool.xa.DruidXADataSource");

ds.setUniqueResourceName("DataSource2");

ds.setPoolSize(5);

ds.setXaProperties(prop);

return ds;

}

@Bean("jdbcTemplate1")

public JdbcTemplate sysJdbcTemplate(@Qualifier("DataSource1") DataSource ds) {

return new JdbcTemplate(ds);

}

@Bean("jdbcTemplate2")

public JdbcTemplate busJdbcTemplate(@Qualifier("DataSource2") DataSource ds) {

return new JdbcTemplate(ds);

}

private Properties build(Environment env, String prefix) {

Properties prop = new Properties();

prop.put("url", env.getProperty(prefix + "url"));

prop.put("username", env.getProperty(prefix + "username"));

prop.put("password", env.getProperty(prefix + "password"));

prop.put("driverClassName", env.getProperty(prefix + "driverClassName", ""));

prop.put("initialSize", env.getProperty(prefix + "initialSize", Integer.class));

prop.put("maxActive", env.getProperty(prefix + "maxActive", Integer.class));

prop.put("minIdle", env.getProperty(prefix + "minIdle", Integer.class));

prop.put("maxWait", env.getProperty(prefix + "maxWait", Integer.class));

prop.put("poolPreparedStatements", env.getProperty(prefix + "poolPreparedStatements", Boolean.class));

prop.put("maxPoolPreparedStatementPerConnectionSize",

env.getProperty(prefix + "maxPoolPreparedStatementPerConnectionSize", Integer.class));

prop.put("maxPoolPreparedStatementPerConnectionSize",

env.getProperty(prefix + "maxPoolPreparedStatementPerConnectionSize", Integer.class));

prop.put("validationQuery", env.getProperty(prefix + "validationQuery"));

prop.put("validationQueryTimeout", env.getProperty(prefix + "validationQueryTimeout", Integer.class));

prop.put("testOnBorrow", env.getProperty(prefix + "testOnBorrow", Boolean.class));

prop.put("testOnReturn", env.getProperty(prefix + "testOnReturn", Boolean.class));

prop.put("testWhileIdle", env.getProperty(prefix + "testWhileIdle", Boolean.class));

prop.put("timeBetweenEvictionRunsMillis",

env.getProperty(prefix + "timeBetweenEvictionRunsMillis", Integer.class));

prop.put("minEvictableIdleTimeMillis", env.getProperty(prefix + "minEvictableIdleTimeMillis", Integer.class));

prop.put("filters", env.getProperty(prefix + "filters"));

return prop;

}

}

2、事務:

@Configuration

@ComponentScan

@EnableTransactionManagement

public class TransactionManagerConfig {

@Bean(name = "userTransaction")

public UserTransaction userTransaction() throws Throwable {

UserTransactionImp userTransactionImp = new UserTransactionImp();

userTransactionImp.setTransactionTimeout(10000);

return userTransactionImp;

}

@Bean(name = "atomikosTransactionManager", initMethod = "init", destroyMethod = "close")

public UserTransactionManager atomikosTransactionManager() throws Throwable {

UserTransactionManager userTransactionManager = new UserTransactionManager();

userTransactionManager.setForceShutdown(false);

return userTransactionManager;

}

@Bean(name = "transactionManager")

@DependsOn({ "userTransaction", "atomikosTransactionManager" })

public JtaTransactionManager transactionManager() throws Throwable {

UserTransaction userTransaction = userTransaction();

JtaTransactionManager manager = new JtaTransactionManager(userTransaction, atomikosTransactionManager());

return manager;

}

@Bean(name = "transactionInterceptor")

public TransactionInterceptor transactionInterceptor(PlatformTransactionManager platformTransactionManager) {

TransactionInterceptor transactionInterceptor = new TransactionInterceptor();

// 事物管理器

transactionInterceptor.setTransactionManager(platformTransactionManager);

Properties transactionAttributes = new Properties();

// test

transactionAttributes.setProperty("test*", "PROPAGATION_REQUIRED,-Throwable");

// 新增

transactionAttributes.setProperty("insert*", "PROPAGATION_REQUIRED,-Throwable");

// 修改

transactionAttributes.setProperty("update*", "PROPAGATION_REQUIRED,-Throwable");

// 刪除

transactionAttributes.setProperty("delete*", "PROPAGATION_REQUIRED,-Throwable");

// 查詢

transactionAttributes.setProperty("select*", "PROPAGATION_REQUIRED,-Throwable,readOnly");

transactionInterceptor.setTransactionAttributes(transactionAttributes);

return transactionInterceptor;

}

// 代理到ServiceImpl的Bean

@Bean

public BeanNameAutoProxyCreator transactionAutoProxy() {

BeanNameAutoProxyCreator transactionAutoProxy = new BeanNameAutoProxyCreator();

transactionAutoProxy.setProxyTargetClass(true);

transactionAutoProxy.setBeanNames("*ServiceImpl");

transactionAutoProxy.setInterceptorNames("transactionInterceptor");

return transactionAutoProxy;

}

}

3、啟動類:

@EnableAutoConfiguration

@ComponentScan

@Configuration

@EnableTransactionManagement(proxyTargetClass = true)

@Import({ DataSourceConfig.class })

public class Application {

public static void main(String[] args) throws Exception {

SpringApplication.run(Application.class, args);

}

}

五、測試代碼:

@Controller

@RequestMapping("/test")

public class TestController {

@Autowired

private JdbcTemplate jdbcTemplate1;

@Autowired

private JdbcTemplate jdbcTemplate2;

@Transactional

@RequestMapping("")

@ResponseBody

public String test() {

//第一個數據採用隨機數,保證第二次能執行

jdbcTemplate1.execute("insert into test_1(id) values("+new Random().nextInt(10000) +")");

//第二條插入語句第二次執行時將報錯,回滾

jdbcTemplate2.execute("insert into test_2(id) values(20)");

return "test ok...";

}

}

springboot+atomikos 分散式事務處理示例

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序員小新人學習 的精彩文章:

windows7上使用docker容器
使用 C 代碼實現拓撲排序

TAG:程序員小新人學習 |