Spring中实现动态数据源切换,基于AbstractRoutingDataSource
背景
在项目开发过程中,我们可能会遇到一个场景:某个类型数据源有多个数据源实例,需要我们按照不同的请求切换到不同数据源去。
而目前绝大多数java应用都是基于Spring框架来开发,我们很多时候相关的数据源连接都是交给了Spring框架去管理,这就需要Spring能够支持动态数据源切换。
方案
Spring中预留了这个接口,通过AbstractRoutingDataSource
能够动态切换数据源。
public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean {
这是一个抽象类,预留了一个抽象方法:
protected abstract Object determineCurrentLookupKey();
我们知道,数据源一般都会提供一个getConnection
方法来获取一个连接,在AbstractRoutingDataSource
实现如下:
@Overridepublic Connection getConnection() throws SQLException {return determineTargetDataSource().getConnection();}protected DataSource determineTargetDataSource() {Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");Object lookupKey = determineCurrentLookupKey();DataSource dataSource = this.resolvedDataSources.get(lookupKey);if (dataSource == null && (this.lenientFallback || lookupKey == null)) {dataSource = this.resolvedDefaultDataSource;}if (dataSource == null) {throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");}return dataSource;}
可以看到,AbstractRoutingDataSource
获取连接的主要逻辑就是通过determineCurrentLookupKey
获取到一个数据源的关联key,然后从resolvedDataSources
中去获取。
而resolvedDataSources
的初始化,则放在afterPropertiesSet
中:
@Overridepublic void afterPropertiesSet() {if (this.targetDataSources == null) {throw new IllegalArgumentException("Property 'targetDataSources' is required");}this.resolvedDataSources = CollectionUtils.newHashMap(this.targetDataSources.size());this.targetDataSources.forEach((key, value) -> {Object lookupKey = resolveSpecifiedLookupKey(key);DataSource dataSource = resolveSpecifiedDataSource(value);this.resolvedDataSources.put(lookupKey, dataSource);});if (this.defaultTargetDataSource != null) {this.resolvedDefaultDataSource = resolveSpecifiedDataSource(this.defaultTargetDataSource);}}
这里起始就是通过targetDataSources
中指定的数据源复制到resolvedDataSources
中去。因此如果多数源是固定的,那么只需要实现determineCurrentLookupKey
方法即可。但是如果多数据源不固定,比如可能会有数据源的变更,那么这种实现是不能够支持,因为这种实现从服务启动的视乎,后续数据源就不能发生变更,这需要我们自己实现determineTargetDataSource
.
下面是一个参考实现:
public class DataSourceContextHolder {private static final ThreadLocal<String> DATASOURCE_CONTEXT_KEY_HOLDER = new ThreadLocal<>();public static void switchDataSource(String key){log.info("Switch to data source:" + key);DATASOURCE_CONTEXT_KEY_HOLDER.set(key);}public static String getDataSourceKey(){return DATASOURCE_CONTEXT_KEY_HOLDER.get() ;}}public class DynamicDataSource extends AbstractRoutingDataSource {private Map<Object, Object> targetDataSources = new HashMap<>();private Map<Object, DataSource> dataSources = new HashMap<>();public DynamicDataSource (){super.setDefaultTargetDataSource(null);super.setTargetDataSources(targetDataSources);super.afterPropertiesSet();}@Overrideprotected DataSource determineTargetDataSource() {Object dataSourceKey = determineCurrentLookupKey();return dataSources.get(dataSourceKey);}@Overrideprotected Object determineCurrentLookupKey() {return DataSourceContextHolder .getDataSourceKey();}public synchronized void addDataSource(String key, DataSource dataSource){targetDataSources.put(key,dataSource);dataSources.put(key,dataSource);log.info("add tenant dynamic dataSource for tenantId = {} ",key);}
}
这样我们通过DataSourceContextHolder
来调整当前线程关联的数据源。
相关文章:
Spring中实现动态数据源切换,基于AbstractRoutingDataSource
背景 在项目开发过程中,我们可能会遇到一个场景:某个类型数据源有多个数据源实例,需要我们按照不同的请求切换到不同数据源去。 而目前绝大多数java应用都是基于Spring框架来开发,我们很多时候相关的数据源连接都是交给了Spring框…...
Linux指标之平均负载(The Average load of Linux Metrics)
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…...
基于SpringBoot共享汽车管理系统【附源码】
基于SpringBoot共享汽车管理系统 效果如下: 系统注册页面 系统登陆页面 系统管理员主页面 用户信息管理页面 汽车投放管理页面 使用订单页面 汽车归还管理页面 研究背景 随着计算机技术和计算机网络的逐渐普及,互联网成为人们查找信息的重要场所。二十…...
React-useState的使用
useState 是 React 提供的一个 Hook,允许你在函数组件中添加和管理状态(state)。在类组件中,状态管理通常是通过 this.state 和 this.setState 来实现的,而在函数组件中,useState 提供了类似的功能。 基本…...
wordpress 中添加图片放大功能
功能描述 使用 Fancybox 实现图片放大和灯箱效果。自动为文章内容中的图片添加链接,使其支持 Fancybox。修改了 header.php 和 footer.php 以引入必要的 CSS 和 JS 文件。在 functions.php 中通过过滤器自动为图片添加 data-fancybox 属性。 最终代码 1. 修改 hea…...
Day 27 贪心算法 part01
贪心算法其实就是没有什么规律可言,所以大家了解贪心算法 就了解它没有规律的本质就够了。 不用花心思去研究其规律, 没有思路就立刻看题解。 基本贪心的题目 有两个极端,要不就是特简单,要不就是死活想不出来。 学完贪心之后再去看动态规划,就会了解贪心和动规的区别。…...
运维面试题.云计算面试题
一、选择题(每题1分,合计15分) 1.若当前目录为 /home,命令 ls–l 将显示 home 目录下的( )。 A.所有文件 B.所有隐含文件 C.所有非隐含文件 D.文件的具体信息 2.如果要列出一个目录下的所有文件需要使用命令行( )。 A. ls–l B. ls C. ls–a(all) D. ls–d 3.下面关于文件…...
计算机专业的真正的就业情况
首先听到计算机行业,大多数人岗位已经饱和,前端已死,程序员35岁危机。但是事实上这些认知都是片面的,今天由我来为大家分析计算机行业的内幕。 疫情过后,过内各种行业都受到了冲击,你们敢说除了体制内的行业…...
行为型模式-状态模式
状态模式(State Pattern)是行为型设计模式之一,用于允许一个对象在其内部状态改变时改变其行为。状态模式可以有效避免在对象中使用大量的条件语句,通过将状态的逻辑转移到独立的状态类中,实现状态与行为的分离。 核心…...
字节跳动青训营刷题笔记19
问题描述 小R正在组织一个比赛,比赛中有 n 支队伍参赛。比赛遵循以下独特的赛制: 如果当前队伍数为 偶数,那么每支队伍都会与另一支队伍配对。总共进行 n / 2 场比赛,且产生 n / 2 支队伍进入下一轮。如果当前队伍数为 奇数&…...
【MATLAB源码-第225期】基于matlab的计算器GUI设计仿真,能够实现基础运算,三角函数以及幂运算。
操作环境: MATLAB 2022a 1、算法描述 界面布局 计算器界面的主要元素分为几大部分:显示屏、功能按钮、数字按钮和操作符按钮。 显示屏 显示屏(Edit Text):位于界面顶部中央,用于显示用户输入的表达式和…...
C++学习日记---第14天(蓝桥杯备赛)
笔记复习 1.对象的初始化和清理 对象的初始化和清理是两个非常重要的安全问题,一个对象或者变量没有初始状态,对其使用后果是未知,同样的使用完一个对象或者变量,没有及时清理,也会造成一定的安全问题 构造函数&…...
windows C#-定义和读取自定义特性
使用特性,可以声明的方式将信息与代码相关联。 特性还可以提供能够应用于各种目标的可重用元素。 考虑 ObsoleteAttribute。 它可以应用于类、结构、方法、构造函数等。 用于声明元素已过时。 然后,由 C# 编译器负责查找此特性,并执行某响应操…...
一个vue项目如何运行在docker
将 Vue.js 应用程序通过 Docker 发布是一个非常常见的做法,它可以帮助你轻松地部署应用到不同的环境中。下面是一个简单的指南,介绍如何为 Vue.js 项目创建 Dockerfile 并进行构建和运行。 第一步:安装 Docker 确保你的开发机器上已经安装了…...
重读《人月神话》(15)-祸起萧墙(Hatching a Catastrophe
增加更多的人手到一个已经延期的项目中往往不会加快项目的进度,反而可能使情况变得更糟。 项目进度的细微延迟往往难以察觉,但它们却能悄无声息地累积起来,最终对整个项目的完成时间造成重大影响。昨天,一位关键成员因突发疾病未…...
【大数据学习 | Spark-Core】广播变量和累加器
1. 共享变量 Spark两种共享变量:广播变量(broadcast variable)与累加器(accumulator)。 累加器用来对信息进行聚合,相当于mapreduce中的counter;而广播变量用来高效分发较大的对象,…...
C/C++基础知识复习(30)
1) 什么是 C 中的 Lambda 表达式?它的作用是什么? Lambda 表达式: 在 C 中,Lambda 表达式是一种可以定义匿名函数的机制,可以在代码中快速创建一个内联的函数对象,而不需要显式地定义一个函数。Lambda 表…...
【Spring MVC】如何获取cookie/session以及响应@RestController的理解,Header的设置
前言 🌟🌟本期讲解关于SpringMVC的编程之参数传递~~~ 🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客 🔥 你的点赞就是小编不断更新的最大动力 🎆那么废…...
Could not locate device support files.
报错信息:Failure Reason: The device may be running a version of iOS (13.6.1 17G80) that is not supported by this version of Xcode.[missing string: 869a8e318f07f3e2f42e11d435502286094f76de] 问题:xcode15升级到xcode16之后,13.…...
Kafka日志索引详解以及生产常见问题分析与总结
文章目录 一、Kafka的Log日志梳理1.1、Topic下的消息如何存储1.1.1、log文件追加记录所有消息1.1.2、index和timeindex加速读取log消息日志 1.2、文件清理机制1.2.1、如何判断哪些日志文件过期了1.2.2、过期的日志文件如何处理 1.3、Kafka的文件高效读写机制1.3.1、Kafka的文件…...
Qt中QGraphics绘图类相关解释
Item(图元)坐标系、Scene(场景)坐标系、View(视图)坐标系,三者均为:x轴正方向向右,y轴正方向向下 1、Item(图元):坐标属于局部坐标,通常以图元中心为原点(中心对称)。 场景坐标系统描述了顶层的图元,每个图…...
@Pattern (用于校验字符串是否符合特定正则表达式)
Pattern 是一个用于校验字符串是否符合特定正则表达式的注解,它在 Java 中常用于验证输入数据的格式。以下是 Pattern 注解的详解和使用方法: 含义 Pattern 注解用于在 Java 中对字段进行注解,以确保其值与指定的正则表达式匹配。这个注解可…...
线程与进程的个人理解
进程(Process): 一个程序在执行时,操作系统为其分配的资源(如内存、CPU 时间等)构成了一个进程。每个进程都有自己的独立的地址空间、堆栈和局部变量,它们之间不共享内存(除非通过特…...
移远通信携手紫光展锐,以“5G+算力”共绘万物智联新蓝图
11月26日,2024紫光展锐全球合作伙伴大会在上海举办。作为紫光展锐重要的合作伙伴,移远通信应邀参会。 在下午的物联网生态论坛上,移远通信产品总监胡勇华作题为“5G与算力双擎驱动 引领智联新未来”的演讲,深度剖析了产业发展的趋…...
【接口封装】——7、连接并使用 MySQL 数据库
头文件: #include <qsqlquery.h> #include <qsqldatabase.h>(注:需要先适配数据库) 函数定义: public:bool verifyLogin(const QString& account, const QString& password);QString getUserName(…...
vue2 中使用 Ag-grid-enterprise 企业版
文章目录 问题Vue2 引入企业版不生效npm run dev 时卡住了94% after seal 卡在这里了测试打包源 git 解决方案记录 问题 我想用企业版的树状表格 Vue2 引入企业版不生效 编译引入 // vue.config.js module.exports {transpileDependencies: ["ag-grid-enterprise"…...
计算机视觉算法:从基础到应用的全面解析
计算机视觉(Computer Vision, CV)是一门研究如何使计算机“看懂”图像和视频的学科。它结合了数学、计算机科学和人工智能的多个领域,旨在通过自动分析和理解数字图像、视频中的内容,模拟人类的视觉感知。计算机视觉算法广泛应用于图像识别、目标检测、自动驾驶、医疗影像等…...
[HCTF 2018]WarmUp
抓包什么也没看到 就是访问这个滑稽的图片 信息收集 这里说明就是他的后台代码 在这个php里面 我们访问 这样就很好看了 代码审计 [HCTF 2018]WarmUp全网最详细解释-CSDN博客 这篇博客讲得真JB好 我就复述下我对博主的理解吧~ 这里我们可以看见白名单是source.php 和h…...
解决jupyter notebook 新建或打开.ipynb 报500 : Internal Server Error(涉及jinja2兼容性问题)
报错: [E 10:09:52.362 NotebookApp] 500 GET /notebooks/Untitled16.ipynb?kernel_namepyt hon3 (::1) 93.000000ms refererhttp://localhost:8888/tree ...... 重点是: from .exporters import * File "C:\ProgramData\Anaconda3\lib\site-p…...
Android 实现悬浮球的功能
Android 实现悬浮球的功能 在 Android 中,实现悬浮球可以通过以下方式实现,常见的方法是使用 WindowManager 创建一个悬浮窗口。以下是具体的实现步骤: 1. 配置权限 在 AndroidManifest.xml 中添加悬浮窗权限: <uses-permis…...
SQL EXISTS 子句的深入解析
SQL EXISTS 子句的深入解析 引言 SQL(Structured Query Language)作为一种强大的数据库查询语言,广泛应用于各种数据库管理系统中。在SQL查询中,EXISTS子句是一种非常实用的工具,用于检查子查询中是否存在至少一行数…...
<项目代码>YOLOv8 红绿灯识别<目标检测>
YOLOv8是一种单阶段(one-stage)检测算法,它将目标检测问题转化为一个回归问题,能够在一次前向传播过程中同时完成目标的分类和定位任务。相较于两阶段检测算法(如Faster R-CNN),YOLOv8具有更高的…...
Linux笔记---进程:进程状态
1. Linux中的进程状态 上图是操作系统学科中,对进程状态的分类。但是这样细致的划分是在操作系统的设计层面上做的,其中的很多细节,用户其实不必关心。 在Linux操作系统中,面向用户层面,对进程状态做了如下的划分&am…...
基于Qt实现的自定义树结构容器:设计与应用
在Qt框架中,尽管其提供了许多强大的容器类(如 QList, QMap, QTreeWidget 等),但缺少一个通用的、灵活的树结构容器,直接支持多层级数据管理。为了满足这些需求,本文设计并实现了一个可复用的自定义树结构容…...
Minio 客户端 mc
1、文档参阅: 1.1、 服务别名设置: https://min.io/docs/minio/linux/reference/minio-mc/mc-alias-set.html 1.2、cp 命令 https://min.io/docs/minio/linux/reference/minio-mc/mc-cp.html 2、mc 命令安装 1、wget https://dl.minio.org.cn/cl…...
python控制鼠标,键盘,adb
python控制鼠标,键盘,adb 听说某系因为奖学金互相举报,好像拿不到要命一样。不禁想到几天前老墨偷走丁胖子的狗,被丁胖子逮到。他面对警察的问询面不改色坚持自我,反而是怒气冲冲的丁胖子被警察认为是偷狗贼。我觉得这…...
使用 Python 剪辑视频的播放速度
要使用 Python 调整视频的播放速度,可以利用 moviepy 库中的 fx(特效)模块来实现这一功能。通过 moviepy.editor 中的 VideoFileClip 类和 fx.speedx 函数,可以轻松地调整视频的播放速度。 安装 moviepy 首先,确保已…...
Scrapy图解工作流程-cnblog
1.1 介绍部分: 文字提到常用的Web框架有Django和Flask,接下来将学习一个全球范围内流行的爬虫框架Scrapy。 1.2 内容部分: Scrapy的概念、作用和工作流程 Scrapy的入门使用 Scrapy构造并发送请求 Scrapy模拟登陆 Scrapy管道的使用 Scrapy中…...
mongodb
MongoDB增加身份验证 - jason47 - 博客园 db.collection.find() - MongoDB 手册 v6.0 1. 登录 rootJTVMbushu104:~# mongosh # 无账号登录 test> use admin # 切换数据库,先切换到有权限数据库再登录授权 switched to db admin admin> db.auth(username,pas…...
海量数据处理面试题
目录 一.位图应用 二.布隆过滤器 三.哈希切割 一.位图应用 1. 给定100亿个整数,设计算法找到只出现一次的整数? 对于这道题100亿个整数大概占用40G,1G2^30byte,所以直接保存是不合适的,可以使用两个位图来处理,用00表示出现0次的,01表示出现一次的,10…...
RNN模型文本预处理--数据增强方法
数据增强方法 数据增强是自然语言处理(NLP)中常用的一种技术,通过生成新的训练样本来扩充数据集,从而提高模型的泛化能力和性能。回译数据增强法是一种常见的数据增强方法,特别适用于文本数据。 回译数据增强法 定义…...
git-显示顺序与提交顺序不一致的问题
问题流程 a分支 初始记录:分支的提交记录是 c1 -> c2 -> c3第一次修改提交记录但并未push:a1(20:18)第二次修改提交记录:a2(20:20) b分支 初始记录: c1 -> c2 -> c3 …...
【软件入门】Git快速入门
Git快速入门 文章目录 Git快速入门0.前言1.安装和配置2.新建版本库2.1.本地创建2.2.云端下载 3.版本管理3.1.添加和提交文件3.2.回退版本3.2.1.soft模式3.2.2.mixed模式3.2.3.hard模式3.2.4.使用场景 3.3.查看版本差异3.4.忽略文件 4.云端配置4.1.Github4.1.1.SSH配置4.1.2.关联…...
基于Springboot的流浪宠物管理系统
基于javaweb的流浪宠物管理系统 介绍 基于javaweb的流浪宠物管理系统的设计与实现,后端框架使用Springbootmybatis,前端框架使用Vuehrml,数据库使用mysql,使用B/S架构实现前台用户系统和后台管理员系统,和不同权限级别…...
【踩坑日记】【教程】如何在ubuntu服务器上配置公钥登录以及bug解决
前言 在日常开发和运维中,为了提高服务器登录的安全性,我们通常会选择使用 SSH 密钥认证 来替代传统的密码登录。然而,在配置 SSH 公钥登录的过程中,可能会遇到各种坑和 Bug。本文将从零开始,手把手教你如何在 Ubuntu…...
使用 VLC 在本地搭建流媒体服务器 (详细版)
提示:详细流程 避坑指南 Hi~!欢迎来到碧波空间,平时喜欢用博客记录学习的点滴,欢迎大家前来指正,欢迎欢迎~~ ✨✨ 主页:碧波 📚 📚 专栏:音视频 目录 借助VLC media pl…...
常用贴片元件封装尺寸
不论你在什么时候开始,重要的是开始之后就不要停止。 一天过完,不会再来。 每一次发奋努力的背后,必有加倍的赏赐。【SMD贴片元件的封装尺寸】 公制:3216——2012——1608——1005——0603——0402 英制:1206——0805—…...
NVR录像机汇聚管理EasyNVR多个NVR同时管理基于B/S架构的技术特点与能力应用
EasyNVR视频融合平台基于云边端协同设计,能够轻松接入并管理海量的视频数据。该平台兼容性强、拓展灵活,提供了视频监控直播、录像存储、云存储服务、回放检索以及平台级联等一系列功能。B/S架构使得EasyNVR实现了视频监控的多元化兼容与高效管理。 其采…...
【时间之外】IT人求职和创业应知【48】-通信技术
目录 新闻一:腾讯科技取得数据显示相关专利 新闻二:中国5G网络规模全球最大,6G技术取得突破 新闻三:亚马逊启动“登月”计划,部署10万颗二代自研芯片 连亚马逊这样的大厂也搞登月计划,可见现在的业界竞争…...
如何为 XFS 文件系统的 /dev/centos/root 增加 800G 空间
如何为 XFS 文件系统的 /dev/centos/root 增加 800G 空间 一、前言二、准备工作三、扩展逻辑卷1. 检查现有 LVM 配置2. 扩展物理卷3. 扩展卷组4. 扩展逻辑卷四、调整文件系统大小1. 检查文件系统状态2. 扩展文件系统五、处理可能出现的问题1. 文件系统无法扩展2. 磁盘空间不足3…...