废话不多说,首先贴配置文件,需要引入pomxml
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.10</version>
</dependency>
<!-- JTA atomikos事务 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-atomikos</artifactId>
</dependency>
JTA/atomikos自行了解
配置文件:
spring:
datasource:
druid:
type: com.alibaba.druid.pool.xa.DruidXADataSource
driver-class-name: com.mysql.jdbc.Driver
platform: mysql
default:
# 资源标识
uniqueResourceName: default
# 数据源类名
xaDataSourceClassName: com.alibaba.druid.pool.xa.DruidXADataSource
# xaDataSourceClassName: org.apache.tomcat.jdbc.pool.DataSource
# xaDataSourceClassName: com.mysql.jdbc.jdbc2.optional.MysqlXADataSource
xaProperties:
# 数据源配置
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://211.149.199.68:3306/mypinyu?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false&pinGlobalTxToPhysicalConnection=true
username: root
password: Goodlan@123
initialSize: 10
minIdle: 10
maxActive: 200
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1 FROM DUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
# 打开PSCache,并且指定每个连接上PSCache的大小
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
#超过时间限制是否回收
removeAbandoned: true
#超时时间;单位为秒。180秒=3分钟
removeAbandonedTimeout: 180
#关闭abanded连接时输出错误日志
# logAbandoned: true
second:
# 资源标识
uniqueResourceName: second
# 数据源类名
xaDataSourceClassName: com.alibaba.druid.pool.xa.DruidXADataSource
# xaDataSourceClassName: com.mysql.jdbc.jdbc2.optional.MysqlXADataSource
# xaDataSourceClassName: org.apache.tomcat.jdbc.pool.DataSource
xaProperties:
driverClassName: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/mypinyu?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false&pinGlobalTxToPhysicalConnection=true
username: root
password: admin
initialSize: 10
minIdle: 10
maxActive: 200
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
#验证连接是否可用,使用的SQL语句
validationQuery: SELECT 1 FROM DUAL #DruidXADataSource pool.DataSource 范围
# testQuery: select 1#MysqlXADataSource范围使用
#指明连接是否被空闲连接回收器(如果有)进行检验.如果检测失败,则连接将被从池中去除.
testWhileIdle: true
#借出连接时不要测试,否则很影响性能
testOnBorrow: false
testOnReturn: false
# 打开PSCache,并且指定每个连接上PSCache的大小
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
#设置连接参数,否则durid在mysql断开连接后连接不上数据库了,配置数据库断开后自动连接
#超过时间限制是否回收
removeAbandoned: true
#超时时间;单位为秒。180秒=3分钟
removeAbandonedTimeout: 180
#关闭abanded连接时输出错误日志
# logAbandoned: true
#jta相关参数配置
jta:
log-dir: classpath:tx-logs
transaction-manager-id: transactionManager
logging.config:
classpath: log4j2.xml
#返回视图的前缀 目录对应src/main/webapp下
spring.mvc.view.prefix: /WEB-INF/jsp/
#返回的后缀
spring.mvc.view.suffix: .jsp
配置:
package com.pinyu.system.global.config.datasource;
import java.util.Properties;
import javax.sql.DataSource;
import javax.transaction.UserTransaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.jta.atomikos.AtomikosDataSourceBean;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.transaction.jta.JtaTransactionManager;
import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.support.http.StatViewServlet;
import com.alibaba.druid.support.http.WebStatFilter;
import com.alibaba.druid.wall.WallConfig;
import com.alibaba.druid.wall.WallFilter;
import com.atomikos.icatch.jta.UserTransactionImp;
import com.atomikos.icatch.jta.UserTransactionManager;
/**
* @author ypp
* 创建时间:2018年11月9日 上午9:36:21
* @Description: TODO(用一句话描述该文件做什么)
*/
@Configuration
public class DruidConfig {
@Bean(DataSourceNames.DEFAULT)
@Primary
@Autowired
public DataSource systemDataSource(Environment env) {
AtomikosDataSourceBean ds = new AtomikosDataSourceBean();
Properties prop = build(env, "spring.datasource.druid."+DataSourceNames.DEFAULT+".");
ds.setXaDataSourceClassName("com.alibaba.druid.pool.xa.DruidXADataSource");
ds.setUniqueResourceName(DataSourceNames.DEFAULT);
ds.setPoolSize(5);
ds.setXaProperties(prop);
return ds;
}
@Autowired
@Bean(name = DataSourceNames.SECOND)
public AtomikosDataSourceBean businessDataSource(Environment env) {
AtomikosDataSourceBean ds = new AtomikosDataSourceBean();
Properties prop = build(env, "spring.datasource.druid."+DataSourceNames.SECOND+".");
ds.setXaDataSourceClassName("com.alibaba.druid.pool.xa.DruidXADataSource");
ds.setUniqueResourceName(DataSourceNames.SECOND);
ds.setPoolSize(5);
ds.setXaProperties(prop);
return ds;
}
/**
* 注入事物管理器
* @return
*/
@Bean("transactionManager")
public JtaTransactionManager regTransactionManager () {
UserTransactionManager userTransactionManager = new UserTransactionManager();
UserTransaction userTransaction = new UserTransactionImp();
return new JtaTransactionManager(userTransaction, userTransactionManager);
}
private Properties build(Environment env, String prefix) {
long minEvictableIdleTimeMillis = Long.parseLong(env.getProperty(prefix + "minEvictableIdleTimeMillis"));
long timeBetweenEvictionRunsMillis = Long.parseLong(env.getProperty(prefix + "timeBetweenEvictionRunsMillis"));
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", Integer.valueOf(env.getProperty(prefix + "initialSize")));
prop.put("minIdle", Integer.valueOf(env.getProperty(prefix + "minIdle")));
prop.put("maxActive", Integer.valueOf(env.getProperty(prefix + "maxActive")));
prop.put("maxWait", Integer.valueOf(env.getProperty(prefix + "maxWait")));
// prop.put("timeBetweenEvictionRunsMillis", timeBetweenEvictionRunsMillis);
// prop.put("minEvictableIdleTimeMillis", minEvictableIdleTimeMillis);
prop.put("validationQuery", env.getProperty(prefix + "validationQuery"));
prop.put("testWhileIdle", Boolean.valueOf(env.getProperty(prefix + "testWhileIdle")));
prop.put("testOnBorrow", Boolean.valueOf(env.getProperty(prefix + "testOnBorrow")));
prop.put("testOnReturn", Boolean.valueOf(env.getProperty(prefix + "testOnReturn")));
return prop;
}
@Bean
public ServletRegistrationBean druidServlet() {
ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new StatViewServlet(), "/druid/*");
//控制台管理用户,加入下面2行 进入druid后台就需要登录
//servletRegistrationBean.addInitParameter("loginUsername", "admin");
//servletRegistrationBean.addInitParameter("loginPassword", "admin");
return servletRegistrationBean;
}
@Bean
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new WebStatFilter());
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
filterRegistrationBean.addInitParameter("profileEnable", "true");
return filterRegistrationBean;
}
@Bean
public StatFilter statFilter(){
StatFilter statFilter = new StatFilter();
statFilter.setLogSlowSql(true); //slowSqlMillis用来配置SQL慢的标准,执行时间超过slowSqlMillis的就是慢。
statFilter.setMergeSql(true); //SQL合并配置
statFilter.setSlowSqlMillis(1000);//slowSqlMillis的缺省值为3000,也就是3秒。
return statFilter;
}
@Bean
public WallFilter wallFilter(){
WallFilter wallFilter = new WallFilter();
//允许执行多条SQL
WallConfig config = new WallConfig();
config.setMultiStatementAllow(true);
wallFilter.setConfig(config);
return wallFilter;
}
}
package com.pinyu.system.global.config.datasource;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
/**
* @author ypp
* 创建时间:2018年11月9日 上午10:09:56
* @Description: TODO(用一句话描述该文件做什么)
*/
@Configuration
@MapperScan(basePackages = "com.pinyu.system.mapper",sqlSessionFactoryRef = "defaultSqlSessionFactory")
public class MybatisDataSourceDefaultConfig {
@Bean
public SqlSessionFactory defaultSqlSessionFactory(@Qualifier(DataSourceNames.DEFAULT)DataSource ds) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(ds);
//指定mapper xml目录
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
factoryBean.setMapperLocations(resolver.getResources("classpath:mapper/**/*Mapper.xml"));
return factoryBean.getObject();
}
@Bean
public SqlSessionTemplate defaultSqlSessionTemplate(@Qualifier("defaultSqlSessionFactory")SqlSessionFactory sf) throws Exception {
SqlSessionTemplate template = new SqlSessionTemplate(sf); // 使用上面配置的Factory
return template;
}
//关于事务管理器,不管是JPA还是JDBC等都实现自接口 PlatformTransactionManager
// 如果你添加的是 spring-boot-starter-jdbc 依赖,框架会默认注入 DataSourceTransactionManager 实例。
//在Spring容器中,我们手工注解@Bean 将被优先加载,框架不会重新实例化其他的 PlatformTransactionManager 实现类。
/*@Bean(name = "transactionManager2")
@Primary
public DataSourceTransactionManager masterTransactionManager() {
//MyBatis自动参与到spring事务管理中,无需额外配置,只要org.mybatis.spring.SqlSessionFactoryBean引用的数据源
// 与DataSourceTransactionManager引用的数据源一致即可,否则事务管理会不起作用。
return new DataSourceTransactionManager(ds);
}*/
}
package com.pinyu.system.global.config.datasource;
import javax.sql.DataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
/**
* @author ypp
* 创建时间:2018年11月9日 上午10:18:03
* @Description: TODO(用一句话描述该文件做什么)
*/
@Configuration
@MapperScan(basePackages = "com.pinyu.system.mapper2",sqlSessionFactoryRef = "secondSqlSessionFactory")
public class MybatisDataSourceSecondConfig {
@Bean
public SqlSessionFactory secondSqlSessionFactory(@Qualifier(DataSourceNames.SECOND)DataSource ds) throws Exception {
SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
factoryBean.setDataSource(ds);
//指定mapper xml目录
ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
factoryBean.setMapperLocations(resolver.getResources("classpath:mapper2/**/*Mapper.xml"));
return factoryBean.getObject();
}
@Bean
public SqlSessionTemplate secondSqlSessionTemplate(@Qualifier("secondSqlSessionFactory")SqlSessionFactory sf) throws Exception {
SqlSessionTemplate template = new SqlSessionTemplate(sf); // 使用上面配置的Factory
return template;
}
//关于事务管理器,不管是JPA还是JDBC等都实现自接口 PlatformTransactionManager
// 如果你添加的是 spring-boot-starter-jdbc 依赖,框架会默认注入 DataSourceTransactionManager 实例。
//在Spring容器中,我们手工注解@Bean 将被优先加载,框架不会重新实例化其他的 PlatformTransactionManager 实现类。
/*@Bean(name = "transactionManager2")
@Primary
public DataSourceTransactionManager masterTransactionManager() {
//MyBatis自动参与到spring事务管理中,无需额外配置,只要org.mybatis.spring.SqlSessionFactoryBean引用的数据源
// 与DataSourceTransactionManager引用的数据源一致即可,否则事务管理会不起作用。
return new DataSourceTransactionManager(ds);
}*/
}
package com.pinyu.system.global.config.datasource;
/**
* @author ypp 创建时间:2018年11月6日 上午11:39:03
* @Description: TODO(数据源常量池)
*/
public interface DataSourceNames {
public static final String DEFAULT = "default";
public static final String SECOND = "second";
}
启动类:
package com.pinyu.system;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.support.SpringBootServletInitializer;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Import;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import com.pinyu.system.global.config.datasource.DruidConfig;
@ComponentScan(basePackages = "com.pinyu.system")
@EnableTransactionManagement(proxyTargetClass = true)
//@SpringBootApplication(exclude={
// DataSourceAutoConfiguration.class,
HibernateJpaAutoConfiguration.class, //(如果使用Hibernate时,需要加)
// DataSourceTransactionManagerAutoConfiguration.class
// })
@SpringBootApplication
@Import(DruidConfig.class)
public class Application extends SpringBootServletInitializer {
}
springboot 检测到jta atomikos环境时,会自动启用分布式事务,给相应的配置,以上配置也是自己摸索出来的,也不敢太深入讲解,怕说错。但亲测可用,多库使用事务也可以回滚。