Spring配置多个数据源并实现数据源的动态切换功能
作者:苹果树上的你
这篇文章主要介绍了Spring配置多个数据源并实现数据源的动态切换功能,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
1.首先在config.properties文件中配置两个数据库连接的基本数据。这个省略了
2.在spring配置文件中配置这两个数据源:
数据源1
<!-- initialSize初始化时建立物理连接的个数0 maxActive最大连接池数量8 minIdle最小连接池数量0--> <bean id="dataSource1" class="com.alibaba.druid.pool.DruidDataSource" scope="singleton"> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <property name="url" value="${jdbc.url}" /> <property name="initialSize" value="${jdbc.init}" /> <property name="maxActive" value="${jdbc.max}" /> <property name="minIdle" value="${jdbc.min}" /> </bean>
数据源2
<bean id="dataSource2" class="com.alibaba.druid.pool.DruidDataSource" scope="singleton"> <property name="username" value="${jdbc.username2}" /> <property name="password" value="${jdbc.password2}" /> <property name="url" value="${jdbc.url2}" /> <property name="initialSize" value="${jdbc.init2}" /> <property name="maxActive" value="${jdbc.max2}" /> <property name="minIdle" value="${jdbc.min2}" /> </bean>
3.自定义一个数据源类,该类继承 org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource
并重写determineCurrentLookupKey()方法
3.1代码如下
public class RoutingDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceHolder.getDataSourceType(); } }
3.2将该类交由sping管理,其在spring配置文件中配置如下
<bean id="dataSource" class="com.coe.exp.core.dataSource.RoutingDataSource"> <!-- 为targetDataSources注入两个数据源 --> <property name="targetDataSources"> <map key-type="java.lang.String"> <entry key="ds1" value-ref="dataSource1"/> <entry key="ds2" value-ref="dataSource2"/> </map> </property> <!-- 为指定数据源RoutingDataSource注入默认的数据源--> <property name="defaultTargetDataSource" ref="dataSource1"/> </bean>
3.3spring其他的配置如下
<!-- MyBatis配置 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 把dataSource注入给sqlSessionFactory --> <property name="dataSource" ref="dataSource" /> <property name="typeAliasesPackage" value="com.coe.exp.core.ent" /> <!-- 指定mapper.xml的位置 --> <property name="mapperLocations" > <array> <value>classpath:com/coe/exp/core/xml/**/*.xml</value> <value>classpath:com/coe/exp/xml/**/*.xml</value> </array> </property> <!-- 指定myBatis配置文件的位置 --> <property name="configLocation" value="classpath:mybatis/sqlmapconfig.xml" /> </bean> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.coe.exp.core.mapper,com.coe.exp.mapper" /> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" /> </bean> <!-- 配置事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="insert*" propagation="REQUIRED"/> <tx:method name="save*" propagation="REQUIRED"/> <tx:method name="update*" propagation="REQUIRED"/> <tx:method name="delete*" propagation="REQUIRED"/> <tx:method name="remove*" propagation="REQUIRED"/> <tx:method name="add*" propagation="REQUIRED"/> <tx:method name="find*" propagation="SUPPORTS"/> <tx:method name="get*" propagation="SUPPORTS"/> </tx:attributes> </tx:advice> <aop:config> <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.coe.exp.dao..*Impl.*(..))" order="2"/> <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.coe.exp.core.dao..*Impl.*(..))" order="3"/> </aop:config> <!-- 注解方式配置事物 --> <tx:annotation-driven transaction-manager="transactionManager" /> <!-- 引入属性文件 --> <context:property-placeholder location="classpath:config.properties" /> <!-- 自动扫描(自动注入) --> <context:component-scan base-package="com.coe.exp,mm" annotation-config="true"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> <context:component-scan base-package="com.coe,mm"/> <!-- 自动扫描定时任务 --> <task:annotation-driven/> <!-- spring自动创建代理,植入切面,proxy-target-class属性,默认为false,表示使用jdk动态代理织入增强,当配为<aop:aspectj-autoproxy poxy-target-class="true"/>时,表示使用CGLib动态代理技术织入增强。不过即使proxy-target-class设置为false,如果目标类没有声明接口,则spring将自动使用CGLib动态代理。 --> <aop:aspectj-autoproxy proxy-target-class="true"/> <import resource="../shiro/spring-shiro.xml"/>
4.编写一个数据源持有类DataSourceHolder
public class DataSourceHolder { private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(); /** * @Description: 设置数据源类型 * @param dataSourceType 数据库类型 * @return void * @throws */ public static void setDataSourceType(String dataSourceType) { contextHolder.set(dataSourceType); } /** * @Description: 获取数据源类型 * @param * @return String * @throws */ public static String getDataSourceType() { return contextHolder.get(); } /** * @Description: 清除数据源类型 * @param * @return void * @throws */ public static void clearDataSourceType() { contextHolder.remove(); } }
5.自定义注解
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import org.springframework.stereotype.Component; /** * 数据源 * * @author llb 2017-03-30 * */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Component public @interface DataSource { String value() default ""; }
6.动态切换数据源
import java.lang.reflect.Method; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Repository; import com.coe.exp.core.dataSource.DataSourceHolder; @Order(1) @Aspect @Repository public class DataSourceAspect { @Pointcut("execution(* com..dao..*Impl.*(..))") private void anyMethod() { } @AfterReturning(value = "anyMethod()", returning = "result") public void afterReturning(JoinPoint joinPoint,Object result){ DataSourceHolder.clearDataSourceType(); } @Before(value="anyMethod()") public void before(JoinPoint joinPoint) throws Throwable { MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); Method method = methodSignature.getMethod(); //如果方法体上使用了DataSource注解 if (method.isAnnotationPresent(DataSource.class)) { //获取该方法上的注解名 DataSource datasource = method.getAnnotation(DataSource.class); //将方法体上的注解的值赋予给DataSourceHolder数据源持有类 DataSourceHolder.setDataSourceType(datasource.value()); } } }
7.若方法体上没有注解,则都是使用默认数据源,如果有以下注解,则使用指定的数据源
/** * 查询哲盟数据库中所有状态正常的客户余额 * @return * @author mxl * @version 2017年8月16日下午1:30:06 */ @DataSource("ds2") public List<CustomerBalanceEnt> getAllCustBalanceByZm(){ return customerBalanceMapper.getAllCustBalanceByZm(); }
上面这个方法就是使用“ds2”;
到此这篇关于Spring配置多个数据源并实现数据源的动态切换的文章就介绍到这了,更多相关Spring配置多个数据源内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!