springmvc动态切换数据源

1.applicationContext.xml

  	<context:property-placeholder location="classpath:jdbc.properties" />
  	<!-- 主数据源 -->
	<bean id="masterDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
		<property name="driverClassName" value="${jdbcDriver}" />
		<property name="url" value="${jdbcUrl}" />
		<property name="username" value="${jdbcUsername}" />
		<property name="password" value="${jdbcPassword}" />
		<property name="maxActive" value="${maxActive}" /><!-- 最大数据库连接数 -->
		<property name="maxIdle" value="${maxIdle}" /><!-- 最大空闲连接数量 -->
		<property name="maxWait" value="${maxWait}" /><!-- 超时等待时间,毫秒 -->
		<property name="testWhileIdle" value="true" /><!-- 连接是否被回收器进行检验 -->
		<property name="testOnBorrow" value="true" /><!-- 是否在从池中取出连接前进行检验 -->
		<property name="validationQuery" value="select 1" />
		<property name="timeBetweenEvictionRunsMillis" value="3600000" /><!-- 每隔多少时间检测一次,毫秒 -->
		<property name="removeAbandoned" value="true" /><!-- 是否自动回收超时连接 -->
 		<property name="removeAbandonedTimeout" value="3600" /><!-- 超时时间,单位秒 -->
	</bean>
	<!-- 从数据源 -->
	<bean id="slaveDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
		<property name="driverClassName" value="${slave_jdbcDriver}" />
		<property name="url" value="${slave_jdbcUrl}" />
		<property name="username" value="${slave_jdbcUsername}" />
		<property name="password" value="${slave_jdbcPassword}" />
		<property name="maxActive" value="${slave_maxActive}" />
		<property name="maxIdle" value="${slave_maxIdle}" />
		<property name="maxWait" value="${slave_maxWait}" />
		<property name="testWhileIdle" value="true" />
		<property name="testOnBorrow" value="true" />
		<property name="validationQuery" value="select 1" />
		<property name="timeBetweenEvictionRunsMillis" value="3600000" />
		<property name="removeAbandoned" value="true" />
 		<property name="removeAbandonedTimeout" value="3600" />
	</bean>
	
	<bean id="dynamicDataSource" class="com.wpao.shop.util.DynamicDataSource">
        <property name="targetDataSources">
            <map key-type="java.lang.String">
               <entry key="master" value-ref="masterDataSource" />
               <entry key="slave" value-ref="slaveDataSource" />
            </map>
        </property>
        <property name="defaultTargetDataSource" ref="masterDataSource" />
    </bean>
	

2.DynamicDataSource

package com.wpao.shop.util;

import org.apache.log4j.Logger;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

//数据源动态切换类:
public class DynamicDataSource extends AbstractRoutingDataSource {
	
	Logger logger = Logger.getLogger(this.getClass());
	  
    @Override
    protected Object determineCurrentLookupKey() {
    	String dtSoce = DataSourceSwitcher.getDataSource();
    	logger.info("***[shopmm]nowLookupKey:"+dtSoce);
        return dtSoce;
    }

}

3.DataSourceSwitcher

package com.wpao.shop.util;

//数据源选择类:
public class DataSourceSwitcher {
	
    @SuppressWarnings("rawtypes")
    private static final ThreadLocal contextHolder = new ThreadLocal();
  
    @SuppressWarnings("unchecked")
    public static void setDataSource(String dataSource) {
        //Assert.notNull(dataSource, "dataSource cannot be null");  
        contextHolder.set(dataSource);
    }  
  
    public static void setMaster() {
        clearDataSource();
        //setDataSource("master");
    }  
  
    public static void setSlave() {
        setDataSource("slave");
    }  

    public static String getDataSource() {
    	
        return (String)contextHolder.get();
    }  
  
    public static void clearDataSource() {
        contextHolder.remove();
    }
    
}

4.DataSourceAdvice

package com.wpao.shop.util;

import java.lang.reflect.Method;
import org.apache.log4j.Logger;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.ThrowsAdvice;

//AOP切面类:
public class DataSourceAdvice implements MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice {
	
	Logger logger = Logger.getLogger(this.getClass());
	
    //service方法执行之前被调用:
    public void before(Method method, Object[] args, Object target) {
    	
    	try {
	    	String inMethdName = (method != null && method.getName() != null) ? method.getName().trim() : "";
	    	//logger.info("***[shopmm]DataSource-切入点:"+target.getClass().getName()+"类中["+inMethdName+"]方法,开始..");
	        String methodName = inMethdName.toLowerCase();
	        if(methodName.startsWith("query")) {
	            DataSourceSwitcher.setSlave();
	            logger.info("***[shopmm]DataSource-切换:["+inMethdName+"]方法已切换到:slave!");
	        }else if(methodName.startsWith("nei")) {
	            //方法的内部方法,不做切换!
	            logger.info("***[shopmm]DataSource-切换:["+inMethdName+"]内部方法不切换!");
	        }else {
	            DataSourceSwitcher.setMaster();
	            logger.info("***[shopmm]DataSource-切换:["+inMethdName+"]方法已切换回:master!");
	        }
    	}catch(Exception e) {
    		DataSourceSwitcher.setMaster();
            logger.info("***[shopmm]DataSource-切换:出现异常,已切换回:master!Err:"+e.toString());
    	}
    }
  
    //service方法执行完之后被调用:
    public void afterReturning(Object arg0, Method method, Object[] args, Object target) {

    	try {
    		DataSourceSwitcher.clearDataSource();
	    	//logger.info("***[shopmm]Aop-Service执行完成:["+method.getName()+"]方法执行结束,clearDataSource!");
    	}catch(Exception e) {
            logger.info("***[shopmm]Aop-Service执行完成:出现异常("+method.getName()+")!Err:"+e.toString());
    	}
    }  
  
    //抛出Exception之后被调用:
    public void afterThrowing(Method method, Object[] args, Object target, Exception ex) {

        try {
    		DataSourceSwitcher.clearDataSource();
	    	logger.info("***[shopmm]Aop-AfterThrowing:"+target.getClass().getName()+"类中["+method.getName()+"]抛出异常["+ex.toString()+"],clearDataSource!");

    	}catch(Exception e) {
            logger.info("***[shopmm]Aop-AfterThrowing:出现异常("+target.getClass().getName()+"-"+method.getName()+")!Err:"+e.toString());
    	}
    }
  
}  

5.applicationContext.xml

    <!-- 切换数据源71209 -->
    <bean id="dataSourceAdvice" class="com.wpao.shop.util.DataSourceAdvice" />
    <aop:config>
        <aop:advisor pointcut="execution(* com.wpao.shop.dao.*.*(..))" advice-ref="dataSourceAdvice" />
    </aop:config>












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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值