題外話:有n個小系統,如今須要用一個系統監控這n個系統中的數據。解決方案能夠是把n個小系統中的數據都同步到一個大的數據庫中,然而,這個並非最佳解決辦法。java
我如今碰到一個問題,就是相似這樣。每一個小系統的數據表,字段、字段類型徹底同樣,實體類也是同樣的,因而,我就想到用mybatis的多數據源切換來解決,因爲這種用法並不常見。能在網上找的資料甚少,因而,查找API、源碼,終於功夫不負有心人,找到了一種比較穩定的解決辦法,寫文以記之。spring
一、首先須要寫出這n個數據源的配置,(這裏以阿里巴巴的數據庫鏈接池爲例,dbcp的鏈接池我試過也是能夠的)數據庫
<bean id="dataSource1" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <property name="maxActive" value="${dbcp.maxActive}" /> <property name="maxIdle" value="${dbcp.maxIdle}" /> <property name="filters" value="stat,log4j" /> <property name="proxyFilters"> <list> <ref bean="stat-filter" /> <ref bean="log-filter" /> </list> </property> <property name="removeAbandoned" value="true"></property> <property name="removeAbandonedTimeout" value="${dbcp.removeAbandoned}"></property> <property name="connectionProperties"><value>clientEncoding=UTF8</value></property> <property name="testWhileIdle"><value>true</value></property> <property name="testOnBorrow"><value>false</value></property> <property name="testOnReturn"><value>false</value></property> <property name="validationQuery"><value>select sysdate from dual</value></property> <property name="validationQueryTimeout"><value>1</value></property> <property name="timeBetweenEvictionRunsMillis"><value>30000</value></property> <property name="numTestsPerEvictionRun"><value>20</value></property> </bean>
如此重複的配置n個不一樣的數據源,以供切換。mybatis
二、數據源配置ui
<bean id="dataSource" class="com.xxx.common.spring.RoutingDataSourceSupport"> <property name="targetDataSources"> <map key-type="java.lang.String"> <entry key="dataSource1" value-ref="dataSource1"/><!-- 如此重複的配置n個須要切換的數據源 --> ... </map> </property> <property name="defaultTargetDataSource" ref="dataSource1"></property><!-- 設置默認的數據源 --> </bean>
三、RoutingDataSourceSupport方法url
package com.xxx.common.spring; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; public class RoutingDataSourceSupport extends AbstractRoutingDataSource { /** 日誌句柄 */ private static Logger logger = LoggerFactory.getLogger(RoutingDataSourceSupport.class); private final static ThreadLocal<String> dataSourceKey = new ThreadLocal<String>(); /** * @param key * 設置當前的數據源 */ public static void setDataSource(String key) { dataSourceKey.set(key); } /** * 恢復默認的數據源 */ public static void clearDataSource() { dataSourceKey.set(null); } protected Object determineCurrentLookupKey() { String key = dataSourceKey.get(); logger.info("當前數據源:"+key); return key; } }
四、如何使用?spa
RoutingDataSourceSupport.setDataSource(dataSource); // 須要執行數據源切換的位置 do something.... RoutingDataSourceSupport.clearDataSource();
後記,也能夠不使用日誌
RoutingDataSourceSupport.clearDataSource();而直接使用
RoutingDataSourceSupport.setDataSource(null);