ssm中多資料來源通過Spring aop 實現資料來源的動態切換
阿新 • • 發佈:2018-12-10
【具體步驟】
1、編寫動態資料來源相關程式碼。
(1) 編寫DynamicDataSource類。
DynamicDataSource的主要作用是以Map的形式,來儲存多個數據源。
因為該類繼承了父類AbstractRoutingDataSource,在父類中,多資料來源的例項是被存放在一個名為“targetDataSource”的Map型別的成員變數中。
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; /** * 實現動態切換資料來源 */ public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DatabaseContextHolder.getDbType(); } }
(2) 編寫DatabaseContextHolder類。
/** * create by ××× on 2018/08/27 */ public class DatabaseContextHolder { private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(); public static void setDbType(String dataSourceType) { contextHolder.set(dataSourceType); } public static String getDbType() { return contextHolder.get(); } public static void clearDbType() { contextHolder.remove(); } }
2、編寫切換資料來源的攔截器。
import org.aspectj.lang.JoinPoint; /** * create by ××× on 2018/08/27 * * 資料來源動態切換攔截器 */ public class DataSourceInterceptor { /** * 資料來源切換常量 */ public static final String MYSQL_DATASOURCE = "mySql"; public static final String SQLSERVER_DATASOURCE = "sqlServer"; /** * 設定mysql資料來源 * * @param jp */ public void setMysqlDatasource(JoinPoint jp) { DatabaseContextHolder.setDbType(MYSQL_DATASOURCE); } /** * 設定資料來源為sqlserver資料庫所對應的資料來源。 * * @param jp */ public void setSqlserverDatasource(JoinPoint jp) { DatabaseContextHolder.setDbType(SQLSERVER_DATASOURCE); } }
3、整體的Spring-mybatis.xml配置。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
<!-- 配置mysql資料來源 -->
<bean id="mySqlDataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="username" value="${connection.mySql.username}"></property>
<property name="password" value="${connection.mySql.password}"></property>
<property name="url" value="${connection.mySql.url}"></property>
<property name="driverClassName" value="${connection.driverClassName}"></property>
<property name="maxActive" value="${connection.maxActive}"></property>
<property name="minIdle" value="${connection.minIdle}"></property>
<property name="filters" value="${connection.filters}"/>
<property name="initialSize" value="${connection.initialSize}"/>
<property name="timeBetweenEvictionRunsMillis" value="${connection.timeBetweenEvictionRunsMillis}"/>
<property name="minEvictableIdleTimeMillis" value="${connection.minEvictableIdleTimeMillis}"/>
<property name="maxOpenPreparedStatements" value="${connection.maxOpenPreparedStatements}"/>
<property name="removeAbandoned" value="${connection.removeAbandoned}"/>
<property name="removeAbandonedTimeout" value="${connection.removeAbandonedTimeout}"/>
<property name="logAbandoned" value="${connection.logAbandoned}"/>
</bean>
<!-- 配置sqlServer資料來源 -->
<bean id="sqlServerDataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="driverClassName" value="${connection.sqlServer.driver}"/>
<property name="url" value="${connection.sqlServer.url}"/>
<property name="username" value="${connection.sqlServer.username}"/>
<property name="password" value="${connection.sqlServer.password}"/>
</bean>
<!-- aop攔截處理,去掉也能執行對應的 dataSource -->
<bean id="dataSource" class="qgs.serviceOperation.dataSourceSwitch.DynamicDataSource">
<property name="defaultTargetDataSource" ref="mySqlDataSource"/> <!--預設主庫-->
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry key="mySql" value-ref="mySqlDataSource"/> <!--輔助aop完成自動資料庫切換-->
<entry key="sqlServer" value-ref="sqlServerDataSource"/>
</map>
</property>
</bean>
<!-- 配置切換資料來源Key的攔截器 -->
<bean id="dataSourceInterceptor" class="qgs.serviceOperation.dataSourceSwitch.DataSourceInterceptor"/>
<!-- myBatis檔案 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="mapperLocations">
<list>
<value>classpath:/mapper/mySql/**/*.xml</value>
<value>classpath:/mapper/sqlServer/*.xml</value>
</list>
</property>
<property name="configLocation">
<value>classpath:spring/mybatis-setting.xml</value>
</property>
</bean>
<!-- mybatis.spring自動對映 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="qgs.serviceOperation.**.dao,qgs.serviceOperation.sqlServer.customInfo.dao"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
<!-- 配置事務管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<aop:aspectj-autoproxy expose-proxy="true"/>
<!-- 註解方式配置事物 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- Spring宣告式事務切面 -->
<tx:advice id="userTxAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="delete*" propagation="REQUIRED" read-only="false"
rollback-for="java.lang.Exception" no-rollback-for="java.lang.RuntimeException"/>
<tx:method name="insert*" propagation="REQUIRED" read-only="false"
rollback-for="java.lang.Exception"/>
<tx:method name="update*" propagation="REQUIRED" read-only="false"
rollback-for="java.lang.Exception"/>
<tx:method name="find*" propagation="SUPPORTS"/>
<tx:method name="get*" propagation="SUPPORTS"/>
<tx:method name="select*" propagation="SUPPORTS"/>
</tx:attributes>
</tx:advice>
<aop:config>
<!-- Spring框架自身提供的切面 -->
<aop:advisor advice-ref="userTxAdvice" pointcut="execution(public * qgs.serviceOperation.*.service..*.*(..))"
order="2"/>
<!-- 使用者自定義的切面,根據切入點,動態切換資料來源。 -->
<aop:aspect id="dataSourceAspect" ref="dataSourceInterceptor" order="1">
<aop:before method="setMysqlDatasource" pointcut="execution(* qgs.serviceOperation.*.service..*.*(..))"/>
<aop:before method="setSqlserverDatasource"
pointcut="execution(* qgs.serviceOperation.sqlServer.customInfo.service..*.*(..))"/>
</aop:aspect>
</aop:config>
</beans>