继承Spring AbstractRoutingDataSource实现路由切换
继承Spring AbstractRoutingDataSource实现路由切换
下面是结合项目整理的如何实现Spring下数据路由动态切换,分三部分,1.配置文件。2.java类。3.总结
一:配置文件
dataAnt.properties:
- driverClass1=oracle.jdbc.driver.OracleDriver
 - jdbcUrl1=jdbc\:oracle\:thin\:@136.160.40.36\:1521\:crmtemp
 - db.user1=crm_app
 - db.password1=abc123
 - driverClass2=oracle.jdbc.driver.OracleDriver
 - jdbcUrl2=jdbc\:oracle\:thin\:@136.160.40.36\:1521\:crmtest
 - db.user2=crm_app
 - db.password2=abc123
 
配置文件,两个jdbc的配置
sm-spring-db.xml:
- <!-- dataAnt默认数据源 -->
 - <bean id="smDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
 - <property name="driverClassName" value="${driverClass1}">
 - </property>
 - <property name="url" value="${jdbcUrl1}">
 - </property>
 - <property name="username" value="${db.user1}">
 - </property>
 - <property name="password" value="${db.password1}">
 - </property>
 - <property name="accessToUnderlyingConnectionAllowed">
 - <value>true</value>
 - </property>
 - </bean>
 - <!-- 数据迁移目标数据源 -->
 - <bean id="qyDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
 - <property name="driverClassName" value="${driverClass2}">
 - </property>
 - <property name="url" value="${jdbcUrl2}">
 - </property>
 - <property name="username" value="${db.user2}">
 - </property>
 - <property name="password" value="${db.password2}">
 - </property>
 - <property name="accessToUnderlyingConnectionAllowed">
 - <value>true</value>
 - </property>
 - </bean>
 - <!-- 数据路由dataSource-->
 - <bean id="dataSource" class="com.ai.data.common.LinkageRoutingDataSource">
 - <property name="targetDataSources">
 - <map key-type="java.lang.String">
 - <entry value-ref="smDataSource" key="smDataSource"></entry>
 - <entry value-ref="qyDataSource" key="qyDataSource"></entry>
 - </map>
 - </property>
 - <property name="defaultTargetDataSource" ref="smDataSource"></property> <!-- 默认使用ds1的数据源 -->
 - </bean>
 
1.这里,配置了两个数据源smDataSource,qyDataSource,并且通过类LinkageRoutingDataSource类实现路由切换。注意设置Bean id为dataSource,保证后面事物控制到对应数据源。
2.bean id = 'dataSource'里注意,必须设置目标数据源targetDataSource和defaultTargetDataSource。
注入jdbcTemplate工具类:
- <!--注入JdbcTemplate切换dataSource工具类[获取bean名,重设dataSource] -->
 - <bean class="com.ai.data.common.JdbcTemplateUtil"></bean>
 
二:java类
LinkageRoutingDataSource.java
- package com.ai.data.common;
 - import org.apache.commons.lang.StringUtils;
 - import org.arrow.common.utils.Log;
 - import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
 - /**
 - * 设置数据源
 - *
 - * @author weiweiai
 - * @see [相关类/方法](可选)
 - * @since [产品/模块版本] (可选)
 - */
 - public class LinkageRoutingDataSource extends AbstractRoutingDataSource {
 - private static final Log log = Log.getLog(LinkageRoutingDataSource.class);
 - //目标数据源
 - private static final ThreadLocal<String> TARGET_DATA_SOURCE = new ThreadLocal<String>();
 - //默认数据源--指标监控的
 - public static final String DEFAULT_DATA_SOURCE = "smDataSource";
 - /**
 - * 根据PrvncUtil类设置进去的当前线程数据源进行数据源切换
 - *
 - * @param 无
 - * @return 数据源名称
 - */
 - protected Object determineCurrentLookupKey() {
 - String targetDataSource = TARGET_DATA_SOURCE.get();
 - if (StringUtils.isEmpty(targetDataSource)) {
 - targetDataSource = DEFAULT_DATA_SOURCE; //默认数据源为指标监控数据源
 - TARGET_DATA_SOURCE.set(targetDataSource);
 - }
 - log.debug("当前线程数据源----------------:{}", targetDataSource);
 - return targetDataSource;
 - }
 - /**
 - * 设置数据源名
 - * @param target
 - */
 - public static void setTargetDataSource(String target) {
 - TARGET_DATA_SOURCE.set(target);
 - }
 - /**
 - * 取数据源名
 - * @return
 - */
 - public static String getTargetDataSource(){
 - return TARGET_DATA_SOURCE.get();
 - }
 - }
 
1.实现Spring提供的AbstractRoutingDataSource抽象类,利用ThreadLocal类型来定义TARGET_DATA_SOURCE(目标数据源),保证线程间数据源名不互相影响。
2.指定默认数据源名,对应第一步中bean id =‘smDataSource’
3.determineCurrentLookupKey这个方法,个人理解,如下图:意思应该是说code想建立数据源连接时候,此方法就会执行目的是找到合适数据源。
这里代码里,就是先取TARGET_DATA_SOURCE线程变量里线程安全的TARGET_DATA_SOURCE,取不到就用默认数据源smDataSource。从而实现bean id='dataSource'属性targetDataSources切换。
PrvncUtil.java
- package com.ai.data.common;
 - import org.apache.commons.lang.StringUtils;
 - import org.arrow.common.utils.Log;
 - /**
 - * 设置获取当前线程数据源名称
 - *
 - * @date 20150924
 - * @author weiweiai
 - */
 - public class PrvncUtil {
 - private static final Log LOG_OUTPUT = Log.getLog(PrvncUtil.class);
 - //默认数据源
 - public static final String DEFAULT_DATA_SOURCE = "smDataSource";
 - /**
 - * 设置需要用的数据源名称
 - *
 - * @param dataSourceName 数据源名称
 - * @retrun 无
 - */
 - public static void setDataSourceName(String dataSourceName) {
 - LinkageRoutingDataSource.setTargetDataSource(getDataSourceName(dataSourceName));
 - }
 - /**
 - * 获取数据源名称
 - * @param dataSourceName
 - * @return 数据源名称
 - */
 - public static String getDataSourceName(String dataSourceName) {
 - String dataSource = dataSourceName;
 - if(StringUtils.isEmpty(dataSource)){
 - dataSource = DEFAULT_DATA_SOURCE;
 - }
 - LOG_OUTPUT.debug("最终获取到的当前数据源名称:{}", dataSource);
 - //((JdbcTemplate)SpringContextHolder.getBean("jdbcTemplate")).setDataSource((DataSource)SpringContextHolder.getBean(dataSource));
 - return dataSource;
 - }
 - }
 
数据路由切换工具类
JdbcTemplateUtil.java
- package com.ai.data.common;
 - import javax.sql.DataSource;
 - import org.springframework.beans.BeansException;
 - import org.springframework.beans.factory.annotation.Autowired;
 - import org.springframework.context.ApplicationContext;
 - import org.springframework.context.ApplicationContextAware;
 - import org.springframework.jdbc.core.JdbcTemplate;
 - import com.linkage.bss.commons.util.StringUtil;
 - /**
 - * JdbcTemplate工具类,实现切换数据源后JdbcTemplate数据源重设
 - * @author weiweiai
 - * 2016/5/10
 - *
 - */
 - public class JdbcTemplateUtil implements ApplicationContextAware{
 - @Autowired
 - private JdbcTemplate jdbcTemplate;
 - public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
 - this.jdbcTemplate = jdbcTemplate;
 - }
 - private ApplicationContext ctx;
 - /*
 - * (non-Javadoc)
 - * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
 - */
 - public void setApplicationContext(ApplicationContext applicationContext)
 - throws BeansException {
 - // TODO Auto-generated method stub
 - this.ctx = applicationContext;
 - }
 - /*
 - * 取LinkageRoutingDataSource 线程变量中数据源,重设jdbcTemplate的数据源属性
 - */
 - public JdbcTemplate getJdbcTemplate(){
 - String ds = LinkageRoutingDataSource.getTargetDataSource();
 - if(!StringUtil.isEmpty(ds))
 - jdbcTemplate.setDataSource((DataSource)ctx.getBean(ds));
 - return jdbcTemplate;
 - }
 - }
 
1.实现ApplicationContextAware接口,且在第一步中已引入,作用是获取到Spring容器中注入的bean。
2.getJdbcTemplate()方法,先获取LinkageRoutingDataSource类中TARGET_DATA_SOURCE线程变量中保存的数据源名。
3.ds为空,返回的是默认数据源;否则切换jdbcTemplate的数据源。
调用:
- PrvncUtil.setDataSourceName("qyDataSource");
 - primaryValueList = jdbcTemplateUtil.getJdbcTemplate().queryForList((String) dataMap.get("SELFORPRIMARY"));
 
三:总结
- PrvncUtil.setDataSourceName("qyDataSource");
 
实现了切换:
primaryValueList = jdbcTemplateUtil.getJdbcTemplate().queryForList((String) dataMap.get("SELFORPRIMARY"));
实现了:
这里为什么jdbcTemplate已经指到dataSource.而dataSource也已经改变属性targetDataSource却没用,我也不懂,欢迎大神指导原因。我已经亲试,确实需要手工
- jdbcTemplate.setDataSource((DataSource)ctx.getBean(ds))
 
不然数据源切不过来,已验证。
继承Spring AbstractRoutingDataSource实现路由切换的更多相关文章
- Spring 实现动态数据源切换--转载 (AbstractRoutingDataSource)的使用
		
[参考]Spring(AbstractRoutingDataSource)实现动态数据源切换--转载 [参考] 利用Spring的AbstractRoutingDataSource解决多数据源的问题 ...
 - 【spring cloud】spring cloud zuul 路由网关
		
GitHub源码地址:https://github.com/AngelSXD/springcloud 版本介绍: <properties> <project.build.source ...
 - spring mvc 多数据源切换,不支持事务控制[一]
		
一个项目中需要使用两个数据库,Oracle 和Mysql ,于是参考各个blog,实现此功能.写好后才发现,原来的事务失效了,我去... spring-mybatis.xml 配置 <bean ...
 - Spring 动态创建并切换数据源
		
公司要求后端项目可以进行动态创建并切换数据源,看了网上很多例子大多数使用的都是Spring内置的AbstractRoutingDataSource进行的,使用此方法不是不行但是有诸多缺陷,比如切换时需 ...
 - 【开发笔记】- AbstractRoutingDataSource动态数据源切换,AOP实现动态数据源切换
		
AbstractRoutingDataSource动态数据源切换 上周末,室友通宵达旦的敲代码处理他的多数据源的问题,搞的非常的紧张,也和我聊了聊天,大概的了解了他的业务的需求.一般的情况下我们都是使 ...
 - AbstractRoutingDataSource动态数据源切换,AOP实现动态数据源切换
		
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/u012881904/article/de ...
 - 基于AbstractRoutingDataSource实现动态切换数据源
		
基于AbstractRoutingDataSource实现动态切换数据源 /** * DataSource注解接口 */ @Target({ElementType.TYPE, ElementTyp ...
 - Spring之多数据源切换的应用
		
这不是一个新的知识点扩展,顶多算是,Spring的AOP特性的一个应用.那么下面开始今天的学习之旅! 场景 数据库读写分离,或者分库,总之多数据源的场景,怎么样实现自动切换(PS:不考虑各种分库分表的 ...
 - Spring多数据源动态切换
		
title: Spring多数据源动态切换 date: 2019-11-27 categories: Java Spring tags: 数据源 typora-root-url: ...... --- ...
 
随机推荐
- A SCSI command code -- SIMPLIFIED DIRECT-ACCESS DEVICE (RBC)
			
SIMPLIFIED DIRECT-ACCESS DEVICE (RBC) ------------------------------------------ OP B Description -- ...
 - svn如何提取文件更新列表
			
eclipse svn插件site-1.10.1 Slik-Subversion-1.8.0-x64.msi ---可以使用svn命令,如svn status 显示修改过的本地文件,如下示例: I: ...
 - java基础学习总结——多态(动态绑定)
			
一.面向对象最核心的机制——动态绑定,也叫多态
 - linux 查找文件命令
			
find -name 文件名 在当前目录下查找 find -name nginx.conf
 - spring Boot打可执行的jar包
			
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://mave ...
 - HDU1561:The more, The Better(树形DP+01背包)
			
Problem Description ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝物.但由于地理位置原因,有 ...
 - 如何记录linux终端下的操作日志
			
如何记录linux终端下的操作日志 在linux终端下,为方便检查操作中可能出现的错误,以及避免屏幕滚屏的限制,我们可以把操作日志记录下来.常用的工具有 screen,script,以及tee等,通过 ...
 - Hashing图像检索源码及数据库总结
			
下面的这份哈希算法小结来源于本周的周报,原本并没有打算要贴出来的,不过,考虑到这些资源属于关注利用哈希算法进行大规模图像搜索的各位看官应该很有用,所以好东西本小子就不私藏了.本资源汇总最主要的收录原则 ...
 - 怎样通过terminal得到AWS EC2 instance的ip
			
可得到private ip,也是本地的ip.事实上通过ifconfig也能得到: GET http://169.254.169.254/latest/meta-data/local-ipv4 公共ip ...
 - MAC 10.10 开机登录无敌风火轮问题解决方式
			
查明是第三方输入法引起的问题,我用的是搜狗输入法.所以把搜狗卸载就好了.(注意是卸载,不是单纯的从输入源里移除) 操作的思路是,首先要进入计算机,才干进行操作. 办法是开机进入单机模式,删除苹果一个文 ...