SpringMvc 4.3 多数据源示例

  由于每个框架不尽相同,所以以下配置仅供参考。我不喜欢说废话,废话说多了一没用,刚才好像打错了一个字,把一改成也,谢谢,好了,废话不多说,我们开始吧!

需呀配置以下文件:
- jdbc.properties
- springMvc-base.xml
- DataSource.class
- DataSourceAspect.class
- DynamicDataSource.class
- DynamicDataSourceHolder.class


jdbc.properties


#####################
#                   #
#     SqlServer     #
#                   #
#####################

driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
url=jdbc:sqlserver://192.168.5.98:1433;databaseName=\u4f60\u731c\u6211\u7528\u7684\u4ec0\u4e48\u540d\u5b57
username=sa
password=sa

#####################
#                   #
#      Oracle       #
#                   #
#####################
driver_two=oracle.jdbc.driver.OracleDriver
url_two=jdbc:oracle:thin:@192.168.5.99:1521:ORCL
username_two=xxxxxxx
password_two=xxxxxxx
validationQuery_two:select 1 from dual

filters:stat
maxActive:20
initialSize:1
maxWait:60000
minIdle:10
maxIdle:15

timeBetweenEvictionRunsMillis:60000
minEvictableIdleTimeMillis:300000

validationQuery:select 1
testWhileIdle:true
testOnBorrow:false
testOnReturn:false

maxOpenPreparedStatements:20
removeAbandoned:true
removeAbandonedTimeout:1800
logAbandoned:true

springMvc-base.xml
这里只贴核心配置
两个druid 连接池配置

<!-- 配置数据源:阿里 druid数据库连接池 -->
    <bean id="dataSource_sqlserver" class="com.alibaba.druid.pool.DruidDataSource"
        destroy-method="close">
        <!-- 数据库基本信息配置 -->
        <property name="url" value="${url}" />
        <property name="username" value="${username}" />
        <property name="password" value="${password}" />
        <property name="driverClassName" value="${driver}" />
        <property name="filters" value="${filters}" />
        <!-- 最大并发连接数 -->
        <property name="maxActive" value="${maxActive}" />
        <!-- 初始化连接数量 -->
        <property name="initialSize" value="${initialSize}" />
        <!-- 配置获取连接等待超时的时间 -->
        <property name="maxWait" value="${maxWait}" />
        <!-- 最小空闲连接数 -->
        <property name="minIdle" value="${minIdle}" />
        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="${timeBetweenEvictionRunsMillis}" />
        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="${minEvictableIdleTimeMillis}" />
        <property name="validationQuery" value="${validationQuery}" />
        <property name="testWhileIdle" value="${testWhileIdle}" />
        <property name="testOnBorrow" value="${testOnBorrow}" />
        <property name="testOnReturn" value="${testOnReturn}" />
        <property name="maxOpenPreparedStatements" value="${maxOpenPreparedStatements}" />
        <!-- 打开removeAbandoned功能 -->
        <property name="removeAbandoned" value="${removeAbandoned}" />
        <!-- 1800秒,也就是30分钟 -->
        <property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}" />
        <!-- 关闭abanded连接时输出错误日志 -->
        <property name="logAbandoned" value="${logAbandoned}" />
    </bean>


    <bean id="dataSource_oracle" class="com.alibaba.druid.pool.DruidDataSource"
          destroy-method="close">
        <!-- 数据库基本信息配置 -->
        <property name="url" value="${url_two}" />
        <property name="username" value="${username_two}" />
        <property name="password" value="${password_two}" />
        <property name="driverClassName" value="${driver_two}" />
        <property name="filters" value="${filters}" />
        <!-- 最大并发连接数 -->
        <property name="maxActive" value="${maxActive}" />
        <!-- 初始化连接数量 -->
        <property name="initialSize" value="${initialSize}" />
        <!-- 配置获取连接等待超时的时间 -->
        <property name="maxWait" value="${maxWait}" />
        <!-- 最小空闲连接数 -->
        <property name="minIdle" value="${minIdle}" />
        <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
        <property name="timeBetweenEvictionRunsMillis" value="${timeBetweenEvictionRunsMillis}" />
        <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
        <property name="minEvictableIdleTimeMillis" value="${minEvictableIdleTimeMillis}" />
        <property name="validationQuery" value="${validationQuery_two}" />
        <property name="testWhileIdle" value="${testWhileIdle}" />
        <property name="testOnBorrow" value="${testOnBorrow}" />
        <property name="testOnReturn" value="${testOnReturn}" />
        <property name="maxOpenPreparedStatements" value="${maxOpenPreparedStatements}" />
        <!-- 打开removeAbandoned功能 -->
        <property name="removeAbandoned" value="${removeAbandoned}" />
        <!-- 1800秒,也就是30分钟 -->
        <property name="removeAbandonedTimeout" value="${removeAbandonedTimeout}" />
        <!-- 关闭abanded连接时输出错误日志 -->
        <property name="logAbandoned" value="${logAbandoned}" />
    </bean>
<!--多数据源选择-->
    <bean id="dataSource" class="com.googosoft.util.double_datasource.DynamicDataSource">
        <property name="targetDataSources">
            <map key-type="java.lang.String">
                <entry value-ref="dataSource_sqlserver" key="dataSource_sqlserver"></entry>
                <entry value-ref="dataSource_oracle" key="dataSource_oracle"></entry>
            </map>
        </property>
    </bean>
<!-- 配置数据库注解aop -->
    <!--多数据源选择-->
    <bean id="dataSourceAspect" class="com.googosoft.util.double_datasource.DataSourceAspect"/>

这里多数据源选择 有一个aop的顺序,不要配置反了

    <aop:config>
        <!-- id:事务切入点名称 expression:事务切入点正则表达式 -->
        <aop:pointcut id="serviceMethods" expression="execution(* com.bjkjdx.serviceImpl..*.*(..))" />
        <!--数据源选择切面,保证在事务开始之前执行-->
        <!--<aop:advisor pointcut-ref="serviceMethods" advice-ref="txAdvice" />-->
        <!--多数据源选择-->
        <aop:advisor pointcut-ref="serviceMethods" advice-ref="dataSourceAspect" order="1" />
        <aop:advisor pointcut-ref="serviceMethods" advice-ref="txAdvice" order="2" />
    </aop:config>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!-- 以delete、insert、update、sava、do、go开头的所有方法采用只读型事务控制类型 -->
            <tx:method name="delete*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" />
            <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="save*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" />
            <tx:method name="do*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" timeout="10" />
            <tx:method name="go*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" timeout="10" />
            <!-- 以load、find、search、select、get开头的所有方法采用只读型事务控制类型 -->
            <tx:method name="load*" propagation="SUPPORTS" read-only="true"/>
            <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
            <tx:method name="search*" propagation="SUPPORTS" read-only="true"/>
            <tx:method name="select*" propagation="SUPPORTS" read-only="true"/>
            <tx:method name="get*" propagation="SUPPORTS" read-only="true"/>
            <tx:method name="*" propagation="SUPPORTS" read-only="true"/>
        </tx:attributes>
    </tx:advice>

然后是代码:(当然我现在的能力还写不出这么NX的代码,谢谢我曾经抄过的某位码神,实在是忘了抄的谁的了,囧)

DataSource.class
使用注解来动态切换数据源

@Documented
@Retention(RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})

public @interface DataSource {
    String name();
//    String name() default DataSource.dataSource_sqlserver;
}

DataSourceAspect.class
监听springmvc框架数据源选择,在事务开始之前,进行数据源切换
这里配置默认的数据源

public class DataSourceAspect implements MethodBeforeAdvice,AfterReturningAdvice
{
    /*调用方法
    * @DataSource(name= DataSourceAspect.dataSource_oracle)
    * */
    public static final String dataSource_sqlserver = "dataSource_sqlserver";
    public static final String dataSource_oracle = "dataSource_oracle";

    @Override
    public void afterReturning(Object returnValue, Method method,
                               Object[] args, Object target) throws Throwable {

        DynamicDataSourceHolder.clearDataSourceType();
    }

    @Override
    public void before(Method method, Object[] args, Object target)
            throws Throwable {

        //首先取类上的数据源
        if(method.getDeclaringClass().isAnnotationPresent(DataSource.class) && !method.isAnnotationPresent(DataSource.class)) {

            DataSource datasource = method.getDeclaringClass().getAnnotation(DataSource.class);
            DynamicDataSourceHolder.setDataSourceType(datasource.name());

            //方法上的数据源 优先级高于类上的
        } else if (method.isAnnotationPresent(DataSource.class)) {

            DataSource datasource = method.getAnnotation(DataSource.class);
            DynamicDataSourceHolder.setDataSourceType(datasource.name());
        }
        else
        {
            DynamicDataSourceHolder.setDataSourceType(dataSource_sqlserver);
        }
    }
}

DynamicDataSource.class
动态数据源类

public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        String dataSource =DynamicDataSourceHolder.getDataSourceType();
        return dataSource;
    }

}

DynamicDataSourceHolder.class
获得和设置上下文环境的类,主要负责改变上下文数据源的名称

public class DynamicDataSourceHolder {
    private static final ThreadLocal<String> contextHolder= new ThreadLocal<String>();

    public static void setDataSourceType(String dataSourceType) {
        contextHolder.set(dataSourceType);
    }

    public static String getDataSourceType() {
        return contextHolder.get();
    }

    public static void clearDataSourceType() {
        contextHolder.remove();
    }
}

使用方法:

在你的service层事务开始的地方,即事务开始之前,使用如下代码切换数据源:

@DataSource(name= DataSourceAspect.dataSource_oracle)

这样就可以实现数据源切换了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值