第一步:
需要禁止掉springboot自生的DataSourceAutoConfiguration
因?yàn)樗鼤?huì)默認(rèn)會(huì)讀取application.properties文件的spring.datasource.*屬性并自動(dòng)配置單數(shù)據(jù)源声诸。
啟動(dòng)類上的注解修改為:
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
第二步
修改配置文件,增加多數(shù)據(jù)源
# 第一數(shù)據(jù)庫(kù)
spring.datasource.pay.url=127.0.0.1:3306
spring.datasource.pay.username=lucode
spring.datasource.pay.password=123
spring.datasource.pay.initialSize=5
spring.datasource.pay.maxActive=20
spring.datasource.pay.minIdle=1
spring.datasource.pay.maxWait=30000
spring.datasource.pay.timeBetweenEvictionRunsMillis=60000
spring.datasource.pay.minEvictableIdleTimeMillis=300000
spring.datasource.pay.poolPreparedStatements=true
spring.datasource.pay.maxPoolPreparedStatementPerConnectionSize=20
spring.datasource.pay.filters=stat, wall, config
# 第二個(gè)數(shù)據(jù)庫(kù)
spring.datasource.travel.url=99.99.99.99:3306
spring.datasource.travel.username=lucode
spring.datasource.travel.password=123
spring.datasource.travel.initialSize=5
spring.datasource.travel.maxActive=20
spring.datasource.travel.minIdle=1
spring.datasource.travel.maxWait=30000
spring.datasource.travel.timeBetweenEvictionRunsMillis=60000
spring.datasource.travel.minEvictableIdleTimeMillis=300000
spring.datasource.travel.poolPreparedStatements=true
spring.datasource.travel.maxPoolPreparedStatementPerConnectionSize=20
spring.datasource.travel.filters=stat, wall, config
第三步
Druid數(shù)據(jù)源讀取配置文件或者普通數(shù)據(jù)源配置
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.sql.SQLException;
@Configuration
@ConfigurationProperties(prefix = "spring.datasource.pay")
public class DruidConfigMetroPay {
public String onoff;
public String url;
public String username;
public String password;
public int initialSize;
public int maxActive;
public int minIdle;
public long maxWait;
public long timeBetweenEvictionRunsMillis;
public long minEvictableIdleTimeMillis;
public boolean poolPreparedStatements;
public int maxPoolPreparedStatementPerConnectionSize;
public String filters;
public String connectionProperties;
public DruidConfigMetroPay() {
}
public DruidConfigMetroPay(String url, String username, String password, int initialSize, int maxActive, int minIdle,
long maxWait, long timeBetweenEvictionRunsMillis, long minEvictableIdleTimeMillis,
boolean poolPreparedStatements, int maxPoolPreparedStatementPerConnectionSize) {
this.url = url;
this.username = username;
this.password = password;
this.initialSize = initialSize;
this.maxActive = maxActive;
this.minIdle = minIdle;
this.maxWait = maxWait;
this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
this.poolPreparedStatements = poolPreparedStatements;
this.maxPoolPreparedStatementPerConnectionSize = maxPoolPreparedStatementPerConnectionSize;
}
@Bean(name="druidDataSourceMetroPay")
public DataSource druidDataSourceMetroPay() {
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setUrl(url);
druidDataSource.setUsername(username);
druidDataSource.setPassword(password);
druidDataSource.setInitialSize(initialSize);
druidDataSource.setMaxActive(maxActive);
druidDataSource.setMinIdle(minIdle);
druidDataSource.setMaxWait(maxWait);
druidDataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
druidDataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
druidDataSource.setPoolPreparedStatements(poolPreparedStatements);
druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
druidDataSource.setConnectionProperties(connectionProperties);
try {
druidDataSource.setFilters("stat,slf4j");
} catch (SQLException e) {
e.printStackTrace();
}
try {
druidDataSource.setFilters(filters);
druidDataSource.init();
} catch (SQLException e) {
e.printStackTrace();
}
return druidDataSource;
}
// 此處省略 get/set 方法
}
注意:
- druidDataSourceMetroPay() 這個(gè)方法的 Bean最好加一下命名瘟芝。
- ConfigurationProperties 的prefix 指定自定義配置的前綴咏闪。如果不嫌麻煩柴钻,可以一個(gè)一個(gè)注入到成員變量究西。
同理另外一個(gè)德魯伊數(shù)據(jù)源
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.sql.SQLException;
@Configuration
@ConfigurationProperties(prefix = "spring.datasource.travel")
public class DruidConfigMetroTravel {
public String onoff;
public String url;
public String username;
public String password;
public int initialSize;
public int maxActive;
public int minIdle;
public long maxWait;
public long timeBetweenEvictionRunsMillis;
public long minEvictableIdleTimeMillis;
public boolean poolPreparedStatements;
public int maxPoolPreparedStatementPerConnectionSize;
public String filters;
public String connectionProperties;
public DruidConfigMetroTravel() {
}
public DruidConfigMetroTravel(String url, String username, String password, int initialSize, int maxActive, int minIdle,
long maxWait, long timeBetweenEvictionRunsMillis, long minEvictableIdleTimeMillis,
boolean poolPreparedStatements, int maxPoolPreparedStatementPerConnectionSize) {
this.url = url;
this.username = username;
this.password = password;
this.initialSize = initialSize;
this.maxActive = maxActive;
this.minIdle = minIdle;
this.maxWait = maxWait;
this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
this.poolPreparedStatements = poolPreparedStatements;
this.maxPoolPreparedStatementPerConnectionSize = maxPoolPreparedStatementPerConnectionSize;
}
@Bean(name="druidDataSourceMetroTravel")
public DataSource druidDataSourceMetroPay() {
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setUrl(url);
druidDataSource.setUsername(username);
druidDataSource.setPassword(password);
druidDataSource.setInitialSize(initialSize);
druidDataSource.setMaxActive(maxActive);
druidDataSource.setMinIdle(minIdle);
druidDataSource.setMaxWait(maxWait);
druidDataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
druidDataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
druidDataSource.setPoolPreparedStatements(poolPreparedStatements);
druidDataSource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
druidDataSource.setConnectionProperties(connectionProperties);
try {
druidDataSource.setFilters("stat,slf4j");
} catch (SQLException e) {
e.printStackTrace();
}
try {
druidDataSource.setFilters(filters);
druidDataSource.init();
} catch (SQLException e) {
e.printStackTrace();
}
return druidDataSource;
}
這樣就定義了兩個(gè)德魯伊數(shù)據(jù)源了.
我們分別命名為druidDataSourceMetroPay
和druidDataSourceMetroTravel
兩個(gè)數(shù)據(jù)源對(duì)應(yīng)著配置上的兩個(gè)數(shù)據(jù)庫(kù)卦碾。
第四步
下面簡(jiǎn)單整合一下德魯伊的基礎(chǔ)配置,只是簡(jiǎn)單做一個(gè)用戶名密碼的的配置,詳細(xì)配置.....不說(shuō)了砚哗。
值得注意的是這個(gè)配置必須優(yōu)先龙助,所以必須加上@Order這個(gè)配置。
import com.alibaba.druid.support.http.StatViewServlet;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
/**
* @author yunfeng.lu
* @create 2017/12/28.
*/
@Configuration
public class DruidServletConfig {
@Bean
@Order
public ServletRegistrationBean statViewServlet() {
StatViewServlet servlet = new StatViewServlet();
ServletRegistrationBean bean = new ServletRegistrationBean(servlet, "/druid/*");
bean.addInitParameter("loginUsername", "lucode");
bean.addInitParameter("loginPassword", "lucode123");
return bean;
}
}
第五步
注冊(cè)MyBatis分頁(yè)插件PageHelper
@Configuration
public class MybatisPageHelperConfig {
@Bean
public PageInterceptor pageHelper() {
PageInterceptor pageHelper = new PageInterceptor();
Properties p = new Properties();
p.setProperty("offsetAsPageNum", "true");
p.setProperty("rowBoundsWithCount", "true");
p.setProperty("reasonable", "true");
pageHelper.setProperties(p);
return pageHelper;
}
}
第六步
最后一步蛛芥,也是將Druid數(shù)據(jù)源整合到 MyBatis 上以及pageHelper的整合提鸟。
import com.github.pagehelper.PageInterceptor;
import org.apache.ibatis.plugin.Interceptor;
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.jdbc.datasource.DataSourceTransactionManager;
import javax.sql.DataSource;
/**
* @author yunfeng.lu
* @create 2017/12/28.
*/
@MapperScan(basePackages = "com.lucode.**.dao.pay",
sqlSessionFactoryRef = "sqlSessionFactoryMetroPay",
sqlSessionTemplateRef = "sqlSessionTemplateMetroPay")
@Configuration
public class MyBatisConfigMetroPay {
// 如果不集成 德魯伊數(shù)據(jù)庫(kù)連接池,需要使用普通的數(shù)據(jù)源仅淑,也在這里配置
// @Autowired
// @Qualifier("metroPay")
// private DataSource dataSourceMetroPay;
/**
* 德魯伊數(shù)據(jù)源
*/
private final DataSource druidDataSourceMetroPay;
private final PageInterceptor pageHelper;
@Autowired
public MyBatisConfigMetroPay(@Qualifier("druidDataSourceMetroPay") DataSource druidDataSourceMetroPay, PageInterceptor pageHelper) {
this.druidDataSourceMetroPay = druidDataSourceMetroPay;
this.pageHelper = pageHelper;
}
@Bean
public SqlSessionFactory sqlSessionFactoryMetroPay() throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(druidDataSourceMetroPay);
sqlSessionFactoryBean.setPlugins(new Interceptor[]{pageHelper});
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
sqlSessionFactoryBean.setMapperLocations(
resolver.getResources("classpath*:com/lucode/**/dao/pay/*.xml"));
SqlSessionFactory sqlSessionFactory = null;
try {
sqlSessionFactory = sqlSessionFactoryBean.getObject();
} catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
org.apache.ibatis.session.Configuration configuration = sqlSessionFactory.getConfiguration();
configuration.setMapUnderscoreToCamelCase(true);
return sqlSessionFactoryBean.getObject();
}
@Bean("metroPayTransaction")
public DataSourceTransactionManager transactionManager() throws Exception {
return new DataSourceTransactionManager(druidDataSourceMetroPay);
}
@Bean
public SqlSessionTemplate sqlSessionTemplateMetroPay() throws Exception {
return new SqlSessionTemplate(sqlSessionFactoryMetroPay());
}
}
解釋一下
MyBatisConfigMetroPay 的構(gòu)造方法称勋,完成了DataSource,PageInterceptor的注入,注意的是 DataSource的注入需要標(biāo)注一下注入 bean 的名字涯竟,也就是剛剛上面配置的 Bean 的名字druidDataSourceMetroPay赡鲜。
-
MapperScan 這個(gè)掃描注解,需要配置掃描的路徑庐船,這里多說(shuō)一下银酬,多數(shù)據(jù)源的 dao 層,兩個(gè)數(shù)據(jù)庫(kù)的 dao筐钟,需要分開放揩瞪,比如我們這里分了 travel 和 pay 兩個(gè)包放 xxxmapper.xml和xxxmapper.java
image.png
至于 pojo 隨便你,放在一起也沒(méi)事篓冲。
sqlSessionFactoryMetroPay和sqlSessionTemplateMetroPay其實(shí)配置一也就可以,但是你配置兩個(gè)系統(tǒng)會(huì)忽略一個(gè)李破。
transactionManager()這個(gè)方法需要特別注意的,這個(gè)事務(wù)相關(guān)的壹将,如果不配置這個(gè)嗤攻,開啟事務(wù)的時(shí)候,就會(huì)出問(wèn)題诽俯。
配置也比較簡(jiǎn)單妇菱,標(biāo)注一下 Bean 的明細(xì),將數(shù)據(jù)源賦值進(jìn)去即可暴区。
那我們?cè)跇I(yè)務(wù)層使用聲明式事務(wù)注解如何使用呢闯团?
@Transactional(propagation = Propagation.REQUIRED,
rollbackFor = Exception.class,
transactionManager = "metroPayTransaction")// 就是在這里指定一下事務(wù)
public void transferCancel(InsideTransferConfirmModel model) {
//忽略方法具體內(nèi)容
}
同理另外一個(gè)數(shù)據(jù)庫(kù)的就在配置一個(gè)
最后文件是這樣的
DruidConfigMetroPay和DruidConfigMetroTravel 完成德魯伊數(shù)據(jù)源的配置
DruidServletConfig和MybatisPageHelperConfig分別完成德魯伊和分頁(yè)插件的配置
MyBatisConfigMetroTravel和MyBatisConfigMetroPay最后完成他們的整合
至于DataSourceConfig其實(shí)是不適用德魯伊數(shù)據(jù)庫(kù)連接池?cái)?shù)據(jù)源的配置
@Configuration
public class DataSourceConfig {
@Bean(name = "metroPay")
@ConfigurationProperties(prefix = "spring.datasource.pay")
public DataSource dataSourceMetroPay() {
return DataSourceBuilder.create().build();
}
@Bean(name = "metroTravel")
@ConfigurationProperties(prefix = "spring.datasource.travel")
public DataSource dataSourceMetroTravel() {
return DataSourceBuilder.create().build();
}
}