ssm中多数据源通过Spring aop 实现数据源的动态切换

【具体步骤】
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>

猜你喜欢

转载自blog.csdn.net/qq_37461349/article/details/82113908