多数据源问题很常见,例如读写分离数据库配置。

1、首先配置多个datasource

  1. <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
  2. <property name="driverClassName" value="net.sourceforge.jtds.jdbc.Driver">
  3. </property>
  4. <property name="url" value="jdbc:jtds:sqlserver://xxx:1433;databaseName=XXX">
  5. </property>
  6. <property name="username" value="XXX"></property>
  7. <property name="password" value="XXX"></property>
  8. </bean>
  9. <bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource">
  10. <property name="driverClassName" value="net.sourceforge.jtds.jdbc.Driver">
  11. </property>
  12. <property name="url" value="jdbc:jtds:sqlserver://XXX:1433;databaseName=XXX">
  13. </property>
  14. <property name="username" value="XXX"></property>
  15. <property name="password" value="XXX"></property>
  16. </bean>

2、写一个DynamicDataSource类继承AbstractRoutingDataSource,并实现determineCurrentLookupKey方法

  1. package com.standard.core.util;
  2. import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
  3. public class DynamicDataSource extends AbstractRoutingDataSource {
  4. @Override
  5. protected Object determineCurrentLookupKey() {
  6. return CustomerContextHolder.getCustomerType();
  7. }
  8. }

3、利用ThreadLocal解决线程安全问题

  1. package com.standard.core.util;
  2. public class CustomerContextHolder {
  3. public static final String DATA_SOURCE_A = "dataSource";
  4. public static final String DATA_SOURCE_B = "dataSource2";
  5. private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
  6. public static void setCustomerType(String customerType) {
  7. contextHolder.set(customerType);
  8. }
  9. public static String getCustomerType() {
  10. return contextHolder.get();
  11. }
  12. public static void clearCustomerType() {
  13. contextHolder.remove();
  14. }
  15. }

4、数据源配置

  1. <bean id="dynamicDataSource" class="com.standard.core.util.DynamicDataSource" >
  2. <property name="targetDataSources">
  3. <map key-type="java.lang.String">
  4. <entry value-ref="dataSource" key="dataSource"></entry>
  5. <entry value-ref="dataSource2" key="dataSource2"></entry>
  6. </map>
  7. </property>
  8. <property name="defaultTargetDataSource" ref="dataSource" >
  9. </property>
  10. </bean>

5、利用拦截器,设置每个请求线程的CustomerContextHolder

  1. public class DatabaseInterceptor implements Interceptor {
  2.  
  3. private static final Logger DB_INC_LOG = LoggerFactory.getLogger(DatabaseInterceptor.class);
  4.  
  5. @Override
  6. public Object invoke(MethodInvocation methodInvocation) throws Throwable {
  7. try {
  8. Method method = methodInvocation.getMethod();
  9. if (method != null && method.getAnnotation(ReadOnlyDataSource.class) != null) {
  10. DataSourceProvider.setDataSource(AvailableDataSources.READ);
  11. }
  12. return methodInvocation.proceed();
  13. } finally {
  14. DataSourceProvider.clearDataSource();
  15. }

6、重写AbstractRoutingDataSource的方法determineCurrentLookupKey(),切换数据源,切换读写

  1. @Override
  2. protected Object determineCurrentLookupKey() {
  3. if (System.currentTimeMillis() - RWSplittingClosed_cache_time <= RW_SPLITTING_CLOSED_TIMEOUT) {
  4. if (RWSplittingClosed_cache) {
  5. return AvailableDataSources.WRITE;
  6. }
  7. return DataSourceProvider.getDataSource();
  8. }
  9. Jedis jedis = null;
  10. try {
  11. jedis = pingJedis();
  12. if (jedis == null) {
  13. return AvailableDataSources.WRITE;
  14. }
  15. Boolean masterForced = Boolean.valueOf(jedis.get(Constants.RW_SPLITTING_CLOSED));
  16. RWSplittingClosed_cache = masterForced;
  17. RWSplittingClosed_cache_time = System.currentTimeMillis();
  18. if (masterForced) {
  19. return AvailableDataSources.WRITE;
  20. }
  21. return DataSourceProvider.getDataSource();
  22. } catch (Exception e) {
  23. log.error(e.getMessage());
  24. return AvailableDataSources.WRITE;
  25. } finally {
  26. if (jedis != null) {
  27. pool.returnResource(jedis);
  28. }
  29. }
  30. }
 

【Spring】26、利用Spring的AbstractRoutingDataSource解决多数据源,读写分离问题的更多相关文章

  1. 利用Spring的AbstractRoutingDataSource解决多数据源的问题【代码手动切换,非AOP】

    转: 利用Spring的AbstractRoutingDataSource解决多数据源的问题 多数据源问题很常见,例如读写分离数据库配置. 原来的项目出现了新需求,局方要求新增某服务器用以提供某代码, ...

  2. 利用Spring的AbstractRoutingDataSource解决多数据源的问题

    多数据源问题很常见,例如读写分离数据库配置. 原来的项目出现了新需求,局方要求新增某服务器用以提供某代码,涉及到多数据源的问题. 解决方法如下: 1.首先配置多个datasource <bean ...

  3. Spring配置动态数据源-读写分离和多数据源

    在现在互联网系统中,随着用户量的增长,单数据源通常无法满足系统的负载要求.因此为了解决用户量增长带来的压力,在数据库层面会采用读写分离技术和数据库拆分等技术.读写分离就是就是一个Master数据库,多 ...

  4. 【Spring】Spring如何实现多数据源读写分离?这是我看过最详细的一篇!!

    写在前面 很多小伙伴私聊我说:最近他们公司的业务涉及到多个数据源的问题,问我Spring如何实现多数据源的问题.回答这个问题之前,首先需要弄懂什么是多数据源:多数据源就是在同一个项目中,会连接两个甚至 ...

  5. 【Spring】利用Spring最简单地使用异步方法

    有时候我们想异步地调用某个方法. 比如这个场景:在业务处理完毕后,需给用户发送通知邮件.由于邮件发送需调用邮箱服务商,有可能发生阻塞,我们就可以异步调用.当然有个前提,即如果邮件发送失败,不需要提示用 ...

  6. 【Spring】利用spring的JdbcTemplate查询返回结果映射到自定义类型

    // org.springframework.jdbc.core.JdbcTemplate 中的查询方法基本都有支持参数RowMapper<T> rowMapper的重载方法.下面只是随便 ...

  7. spring项目配置双数据源读写分离

    我们最早做新项目的时候一直想做数据库的读写分离与主从同步,由于一些原因一直没有去做这个事情,这次我们需要配置双数据源的起因是因为我们做了一个新项目用了另一个数据库,需要把这个数据库的数据显示到原来的后 ...

  8. 在应用层通过spring特性解决数据库读写分离

    如何配置mysql数据库的主从? 单机配置mysql主从:http://my.oschina.net/god/blog/496 常见的解决数据库读写分离有两种方案 1.应用层 http://neore ...

  9. 使用Spring AOP实现读写分离(MySql实现主从复制)

    1.  背景 我们一般应用对数据库而言都是“读多写少”,也就说对数据库读取数据的压力比较大,有一个思路就是说采用数据库集群的方案,其中一个是主库,负责写入数据,我们称之为:写库: 其它都是从库,负责读 ...

随机推荐

  1. Xcode8.0 / OS X EI Capitan 10.11.6 提交报错90111

    改用新系统和新版xcode(都是正式版)后,提交App Store审核时报错: INFO ITMS-90111: "Beta Toolchain. 构建新的 App 和App 更新时,必须使 ...

  2. 安卓Task和Back Stack

    概述 一个Activity允许用户完成一些操作,甚至,Android中设计Activity为组件的形式,这样,多个Activity--甚至是其它App的Activity可以一起完成一项任务. Task ...

  3. php安装扩展的几种方法

    转自:http://doc3.workerman.net/appendices/install-extension.html 安装扩展 注意 与Apache+PHP或者Nginx+PHP的运行模式不同 ...

  4. Android-如何显示版本号并制作3秒跳转页

    前言 大家好,给大家带来Android-如何显示版本号并制作3秒跳转页的概述,希望你们喜欢 软件技术人员,时代作者,从 Android 到全栈之路,我相信你也可以!阅读他的文章,会上瘾!You and ...

  5. Redis 分布式锁进化史(解读 + 缺陷分析)

    Redis分布式锁进化史 近两年来微服务变得越来越热门,越来越多的应用部署在分布式环境中,在分布式环境中,数据一致性是一直以来需要关注并且去解决的问题,分布式锁也就成为了一种广泛使用的技术,常用的分布 ...

  6. Info - 信息获取途径汇总

    目的驱动 大多数情况下,都是为了解决某个问题或完成某项任务,才需要进行针对性的.大范围的.细致化的信息获取. 那么,信息获取的方式和来源,就应该紧紧围绕这个"问题和任务"本身来确定 ...

  7. HoloLens开发手记 - 使用Windows设备控制台 Using Windows Device Portal

    Windows设备控制台允许你通过Wi-Fi或USB来远程控制你的HoloLens设备.设备控制台是HoloLens上的一个Web Server,你可以通过PC的浏览器来连接到它.设备控制台包含了很多 ...

  8. 【2019北京集训测试赛(十三)】数据(sj) 冷静分析

    题目大意:给你一个代表区间$[1,n]$的线段树,问你随机访问区间$[1,n]$中的一个子区间,覆盖到的线段树节点个数的期望(需要乘上$\frac{n(n-1)}{2}$后输出). 数据范围:$n≤1 ...

  9. 自动化测试工具selenium webdirver

    看视频学到的,自动化测试工具,可以模拟用户操作,包括输入,点击等操作 新建新文件夹 在命令行执行npm init  ,一路回车,把项目先初始化 安装  npm install selenium-web ...

  10. Visual Studio For MacOS 踩坑记(二)

    Visual Studio For MacOS安装安卓SDK. 系统默认安装了安卓6.0  API23的SDK.  但是我需要安卓7.0的,API24.  遂安装. SDK可以下载成功,但是用Visu ...