在本项目中,连接了两个数据库,分别是management和platform库
一、调整数据库配置文件database.properties,配置多个jdbc连接
url_platform=jdbc:mysql://xxx.xxx.x.xx:xxxx/platform?characterEncoding=utf-8&allowMultiQueries=true&serverTimezone=GMT%2B8&noAccessToProcedureBodies=true&useAffectedRows=true driver_platform=com.mysql.jdbc.Driver user_platform=xxxx password_platform=xxxx url_management=jdbc:mysql://xxx.xxx.x.xx:xxxx/management?characterEncoding=utf-8&allowMultiQueries=true&serverTimezone=GMT%2B8&noAccessToProcedureBodies=true&useAffectedRows=true driver_management=com.mysql.jdbc.Driver user_management=xxxx password_management=xxxx
三、项目代码完善
新建enum表示不同的数据源
package com.kongpkp.enums; public enum DataSources { Platform, Management }
通过 TheadLocal 来保存每个线程选择哪个数据源的标志(key):
package com.kongpkp.dataSource; import com.kongpkp.enums.DataSources; public class DataSourceTypeManager { private static final ThreadLocal<DataSources> dataSourceTypes = new ThreadLocal<DataSources>(){ @Override protected DataSources initialValue(){ return DataSources.Platform; } }; public static DataSources get(){ return dataSourceTypes.get(); } public static void set(DataSources dataSourceType){ dataSourceTypes.set(dataSourceType); } public static void reset(){ dataSourceTypes.set(DataSources.Platform); } }
定义 ThreadLocalRountingDataSource,继承AbstractRoutingDataSource:
package com.kongpkp.dataSource; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; public class ThreadLocalRountingDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DataSourceTypeManager.get(); } }
在配置文件applicationContext.xml中向 ThreadLocalRountingDataSource 注入 management和 platform 的数据源:
<?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" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd"> <!--扫描dao和service层的注解--> <context:component-scan base-package="com.kongpkp.infrastructure"/> <!--引入database.properties文件、配置数据源连接--> <context:property-placeholder location="classpath:database.properties"/> <!--配置数据源连接 platform --> <bean id="dataSource_platform" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="url" value="${url_platform}"/> <property name="username" value="${user_platform}"/> <property name="password" value="${password_platform}"/> <!-- 初始化连接大小 --> <property name="initialSize" value="0" /> <!-- 连接池最大使用连接数量 --> <property name="maxActive" value="20" /> <!-- 连接池最大空闲 --> <property name="maxIdle" value="20" /> <!-- 连接池最小空闲 --> <property name="minIdle" value="0" /> <!-- 获取连接最大等待时间 --> <property name="maxWait" value="60000" /> </bean> <!--配置数据源连接 management --> <bean id="dataSource_management" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close"> <property name="url" value="${url_management}"/> <property name="username" value="${user_management}"/> <property name="password" value="${password_management}"/> <!-- 初始化连接大小 --> <property name="initialSize" value="0" /> <!-- 连接池最大使用连接数量 --> <property name="maxActive" value="20" /> <!-- 连接池最大空闲 --> <property name="maxIdle" value="20" /> <!-- 连接池最小空闲 --> <property name="minIdle" value="0" /> <!-- 获取连接最大等待时间 --> <property name="maxWait" value="60000" /> </bean> <bean id="dataSource" class="com.kongpkp.dataSource.ThreadLocalRountingDataSource"> <property name="defaultTargetDataSource" ref="dataSource_platform" /> <property name="targetDataSources"> <map key-type="com.kongpkp.enums.DataSources"> <entry key="Platform" value-ref="dataSource_platform"/> <entry key="Management" value-ref="dataSource_management"/> <!-- 这里还可以加多个dataSource --> </map> </property> </bean> <!--创建sqlSessionFactory对象--> <bean id="sqlSessionFactory" class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configuration"> <bean class="com.baomidou.mybatisplus.core.MybatisConfiguration"> <property name="autoMappingBehavior" value="FULL"/> <property name="mapUnderscoreToCamelCase" value="true"/> </bean> </property> <!--分页插件--> <property name="plugins"> <array> <bean class="com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor"> <property name="dbType" value="MYSQL"/> </bean> </array> </property> </bean> <!-- Transaction manager for a single JDBC DataSource --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 使用annotation定义事务 --> <tx:annotation-driven transaction-manager="transactionManager" /> <!--递归扫描dao成接口,进行动态映射--> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.kongpkp.infrastructure.mapper"/> </bean> </beans>
使用Spring AOP 来指定 dataSource 的 key ,从而dataSource会根据key选择 dataSource_platform 和 dataSource_management:
package com.kongpkp.aop; import com.kongpkp.dataSource.DataSourceTypeManager; import com.kongpkp.enums.DataSources; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @Aspect // for aop @Component // for auto scan @Order(0) // execute before @Transactional public class DataSourceInterceptor { @Pointcut("execution(public * com.kongpkp.controller.IndexController.login(..))") public void dataSourceSlave(){ System.out.println("Pointcut"); }; @Before("dataSourceSlave()") public void before(JoinPoint jp) { System.out.println("before"); DataSourceTypeManager.set(DataSources.Management); } }
启动项目,调用接口,访问的是com.kongpkp.controller.IndexController.login的方法,会连接到management库,调用其余的方法,会连接到platform库