springMVC+mybatis的多数据动态切换

扩展AbstractRoutingDataSource

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

/**
 * 
 * <p>Title: DynamicDataSource</p>  
 * <p>Description: 动态数据源(依赖于spring)</p>  
 * @author zhjie  
 * @date 
 */

public class DynamicDataSource extends AbstractRoutingDataSource {

	@Override
	protected Object determineCurrentLookupKey() {
		return DataSourceContextHolder.getDataSource();
	}

}

DataSourceContextHolder 数据源操作类

/**
 * 
 * <p>Title: DataSourceContextHolder</p>  
 * <p>Description: 数据源进行操作的类</p>  
 * @author zhjie  
 * @date 
 */
public class DataSourceContextHolder {  

	/**
	 * 线程本地环境
	 */
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();  

    /** 
     * @Description: 设置数据源
     * @param dataSource  数据源名称
     * @return void 
     * @throws 
     */  
    public static void setDataSource(String dataSource) {  
        contextHolder.set(dataSource);  
    }  

    /** 
     * @Description: 获取数据源名称 
     * @param  
     * @return String 
     * @throws 
     */  
    public static String getDataSource() {  
        return contextHolder.get();  
    }  

    /** 
     * @Description: 清除数据源名称
     * @param  
     * @return void 
     * @throws 
     */  
    public static void clearDataSource() {  
        contextHolder.remove();  

    }  

}  

数据源自定义注解

/**
 * 
 * <p>Title: DataSource</p>  
 * <p>Description: 数据源自定义注解</p>  
 * @author zhjie  
 * @date 
 */
@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DataSource {

	String name() default DataSource.PORTAL;

	public static String PORTAL = "dataSourcePortal";
	public static String EMP = "dataSourceEmp";
}

在service层使用数据源自定义注解

@Service
@DataSource(name = DataSource.EMP)
public class EmpServeiceImpl implements EmpService {

	@Autowired
	private EmpDao empDao ;
	@Override
	public int addEmp(Emp emp) {
		return empDao.addEmp(emp);
	}
	
	@Override
	public int deleteEmp(Emp emp) {
		return empDao.deleteEmp(emp);
	}

	@Override
	public int updateEmp(Emp emp) {
		return empDao.updateEmp(emp);
	}

	@Override
	public List<Emp> getEmps(Emp emp) {
		return empDao.getEmps(emp);
	}

	@Override
	public int getCount(Emp emp) {
		return empDao.getCount(emp);
	}


}

自定义拦截器,拦截DataSource的值,用于切换数据源

/**
 * 自定义拦截器,拦截DataSource的值
 * <p>Title: DataSourceExchange</p>  
 * <p>Description: </p>  
 * @author zhjie  
 * @date 
 */
public class DataSourceExchange implements MethodBeforeAdvice,AfterReturningAdvice 

{

	@Override
	public void afterReturning(Object returnValue, Method method,
			Object[] args, Object target) throws Throwable {
		DataSourceContextHolder.clearDataSource();
	}

	@Override
	public void before(Method method, Object[] args, Object target){
		Class<?> clazz = target.getClass();
		try {
            Class<?>[] types = method.getParameterTypes();
            // 默认使用类型注解
            if (clazz.isAnnotationPresent(DataSource.class)) {
                DataSource source = clazz.getAnnotation(DataSource.class);
                DataSourceContextHolder.setDataSource(source.name());
            }
            // 方法注解可以覆盖类型注解
            Method m = clazz.getMethod(method.getName(), types);
            if (m != null && m.isAnnotationPresent(DataSource.class)) {
                DataSource source = m.getAnnotation(DataSource.class);
                DataSourceContextHolder.setDataSource(source.name());
            }
        } catch (Exception e) {
            System.out.println(clazz + ":" + e.getMessage());
        }

	}

}

数据源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:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context 
       http://www.springframework.org/schema/context/spring-context.xsd 
       ">
  
	<!-- 加载db.properties文件中的内容 -->
	<context:property-placeholder location="classpath:config/properties/mysql.properties" />   
	  
	<!-- 配置数据源,-->
	<bean id="dataSourcePortal" class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close">
        <property name="driverClassName" value="${portal.jdbc.driver}" />
        <property name="url" value="${portal.jdbc.url}" />
        <property name="username" value="${portal.jdbc.uname}" />
        <property name="password" value="${portal.jdbc.password}" />
        <!-- 初始化连接大小 -->
        <property name="initialSize" value="${portal.jdbc.initialSize}"></property>
        <!-- 连接池最大数量 -->
        <property name="maxActive" value="${portal.jdbc.maxActive}"></property>
        <!-- 连接池最大空闲 -->
        <property name="maxIdle" value="${portal.jdbc.maxIdle}"></property>
        <!-- 连接池最小空闲 -->
        <property name="minIdle" value="${portal.jdbc.minIdle}"></property>
        <!-- 获取连接最大等待时间 -->
        <property name="maxWait" value="${portal.jdbc.maxWait}"></property>
		<!-- 
        <property name="driverClassName" value="${driver}" />
        <property name="url" value="${url}" />
        <property name="username" value="${username}" />
        <property name="password" value="${password}" />
        <property name="initialSize" value="${initialSize}"></property>
        <property name="maxActive" value="${maxActive}"></property>
        <property name="maxIdle" value="${maxIdle}"></property>
        <property name="minIdle" value="${minIdle}"></property>
        <property name="maxWait" value="${maxWait}"></property>
         -->
	</bean>
	<!-- 配置数据源,-->
	<bean id="dataSourceEmp" class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close">
        <property name="driverClassName" value="${emp.jdbc.driver}" />
        <property name="url" value="${emp.jdbc.url}" />
        <property name="username" value="${emp.jdbc.uname}" />
        <property name="password" value="${emp.jdbc.password}" />
        <!-- 初始化连接大小 -->
        <property name="initialSize" value="${emp.jdbc.initialSize}"></property>
        <!-- 连接池最大数量 -->
        <property name="maxActive" value="${emp.jdbc.maxActive}"></property>
        <!-- 连接池最大空闲 -->
        <property name="maxIdle" value="${emp.jdbc.maxIdle}"></property>
        <!-- 连接池最小空闲 -->
        <property name="minIdle" value="${emp.jdbc.minIdle}"></property>
        <!-- 获取连接最大等待时间 -->
        <property name="maxWait" value="${emp.jdbc.maxWait}"></property>
	</bean>
	<!-- 数据源:Spring用来控制业务逻辑。数据源、事务控制、aop -->
     <bean id="dataSource" class="com.zhjie.common.datasource.DynamicDataSource">
         <property name="targetDataSources">
             <map key-type="java.lang.String">
                 <entry key="dataSourcePortal" value-ref="dataSourcePortal"></entry>
                 <entry key="dataSourceEmp" value-ref="dataSourceEmp"></entry>
             </map>
         </property>
         <!-- 默认目标数据源为你主库数据源 -->
         <property name="defaultTargetDataSource" ref="dataSourcePortal"/>
     </bean>
	<!-- 配置sqlSessionFactory -->
	<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="dataSource" /><!-- 实例化sqlSessionFactory时需要使用上述配置好的数据源以及SQL映射文件 -->
		<property name="mapperLocations" value="classpath*:mybatis/mappers/**/*.xml" /><!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 -->
		<property name="configLocation" value="classpath:config/xml/mybatis-config.xml"/>
	</bean>
	
	<bean id="dataSourceExchange" class="com.zhjie.common.datasource.DataSourceExchange"/>
	
	<!-- 定义SqlSessionTemplate -->
	<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
		<constructor-arg index="0" ref="sqlSessionFactory"></constructor-arg>
	</bean>

	<!-- SqlSession:用于执行持久化操作的对象,类似于jdbc中的Connection。  -->
	<!-- SqlSessionFactory:创建SqlSession实例的工厂 -->
	<!-- SqlSessionFactoryBuilder:build方法创建SqlSessionFactory实例。 -->
	<!-- SqlSessionTemplate:MyBatis提供的持久层访问模板化的工具,线程安全,可通过构造参数或依赖注入SqlSessionFactory实例。 -->
	
	
</beans>

配置切面拦截

<aop:config>		
	    <!--pointcut元素定义一个切入点,execution中的第一个星号 用以匹配方法的返回类型, 这里星号表明匹配所有返回类型。 com.zhjie.servie.*.*(..)表明匹配cn.zhjie.service包下的所有类的所有方法 -->		
	    <aop:pointcut id="myPointcut"			
	    expression="execution(* com.zhjie.portal.service.*.*(..)) or execution(* com.zhjie.emp.service.*.*(..))" />		
	    <!--将定义好的事务处理策略应用到上述的切入点 -->		
	    <aop:advisor advice-ref="txAdvice" pointcut-ref="myPointcut" order="2"/>	
	    <aop:advisor pointcut-ref="myPointcut" advice-ref="dataSourceExchange" order="1" />
	</aop:config>

搞定!!!

有问题欢迎吐槽。。。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值