从此抄录:https://blog.csdn.net/ll535299/article/details/78203634
1、先配置两个数据源,附上主要代码,给自己回忆,详解见开头链接
<!-- 配置数据源 --> <bean id="szDS" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="url" value="${szds.dbhost}"/> <property name="username" value="${szds.dbusername}"/> <property name="password" value="${szds.dbpwd}"/> <property name="initialSize" value="1"/> <property name="minIdle" value="1"/> <property name="maxActive" value="30"/> <property name="maxWait" value="${szds.maxWait}"/> <property name="timeBetweenEvictionRunsMillis" value="${szds.timeBetweenEvictionRunsMillis}"/> <property name="minEvictableIdleTimeMillis" value="${szds.minEvictableIdleTimeMillis}"/> <property name="validationQuery" value="SELECT 'j'"/> <property name="testWhileIdle" value="true"/> <property name="testOnBorrow" value="false"/> <property name="testOnReturn" value="false"/> <property name="poolPreparedStatements" value="false"/> <property name="filters" value="${szds_common.filters}"/> <property name="connectionProperties" value="${szds_common.connectionProperties}"/> </bean> <!-- 配置上报系统数据源 --> <bean id="tntDS" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="url" value="${szds_tnt.dbhost}"/> <property name="username" value="${szds_tnt.dbusername}"/> <property name="password" value="${szds_tnt.dbpwd}"/> <property name="initialSize" value="1"/> <property name="minIdle" value="1"/> <property name="maxActive" value="30"/> <property name="maxWait" value="${szds_tnt.maxWait}"/> <property name="timeBetweenEvictionRunsMillis" value="${szds_tnt.timeBetweenEvictionRunsMillis}"/> <property name="minEvictableIdleTimeMillis" value="${szds_tnt.minEvictableIdleTimeMillis}"/> <property name="validationQuery" value="SELECT 'j'"/> <property name="testWhileIdle" value="true"/> <property name="testOnBorrow" value="false"/> <property name="testOnReturn" value="false"/> <property name="poolPreparedStatements" value="false"/> <property name="filters" value="${szds_common.filters}"/> <property name="connectionProperties" value="${szds_common.connectionProperties}"/> </bean>
2、自定义一个数据源类,该类继承 org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource并重写determineCurrentLookupKey()方法
public class RoutingDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceHolder.getDataSourceType(); } }
3、将该类交由sping管理,其在spring配置文件中配置如下
<bean id="dataSource" class="com.wayyue.sz.asgard.admin.dataSource.RoutingDataSource"> <!-- 为targetDataSources注入两个数据源 --> <property name="targetDataSources"> <map key-type="java.lang.String"> <entry key="szDS" value-ref="szDS"/> <entry key="tntDS" value-ref="tntDS"/> </map> </property> <!-- 为指定数据源RoutingDataSource注入默认的数据源--> <property name="defaultTargetDataSource" ref="szDS"/> </bean>
4、事务配置如下
<!-- 开启aop注解--> <aop:aspectj-autoproxy proxy-target-class="true"/> <!-- mybatis 配置--> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="mapperLocations" value="classpath:sqlmap/*.xml"/> </bean> <bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.wayue.sz.biz.orm.mapper"/> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> </bean> <!-- 配置事物管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 开启注解控制事物--> <tx:annotation-driven transaction-manager="transactionManager"/>
5、编写一个数据源持有类DataSourceHolder
package com.wayyue.sz.asgard.admin.dataSource; public class DataSourceHolder { private static final ThreadLocal<String> contextHolder = new ThreadLocal<>(); /** * 设置数据源类型 * * @param dataSourceType 数据库类型 */ public static void setDataSourceType(String dataSourceType) { contextHolder.set(dataSourceType); } /** * 获取数据源类型 * * @return */ public static String getDataSourceType() { return contextHolder.get(); } /** * 清除数据源类型 */ public static void clearDataSourceType() { contextHolder.remove(); } }
6.自定义注解
package com.wayyue.sz.asgard.admin.aspect; import java.lang.annotation.*; /** * 数据源 * * @author xxx * @date 2018年11月19日21:05:13 */ @Target({ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Inherited public @interface DataSource { String value() default ""; }
7、动态切换数据源
package com.wayyue.sz.asgard.admin.aspect; import com.wayyue.sz.asgard.admin.dataSource.DataSourceHolder; 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.stereotype.Repository; import java.lang.reflect.Method; @Aspect @Repository public class DataSourceAspect { @Pointcut("execution(* com.wayyue.sz.asgard.admin.service.tnt..*.*(..))") 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()); } } }
8、若方法体上没有注解,则都是使用默认数据源,如果有以下注解,则使用指定的数据源
@Override @DataSource("tntDS") public String getDeal() { // 新数据源 String s = tntDealInfoMapper.dockingOrderCode(); return s; } @Override public String getCode() { // 默认数据源 return tntDealInfoMapper.getCode(); }