当前位置: 首页 > news >正文

SpringBoot 手动实现动态切换数据源 DynamicSource (中)

大家好,我是此林。

SpringBoot 手动实现动态切换数据源 DynamicSource (上)-CSDN博客

在上一篇博客中,我带大家手动实现了一个简易版的数据源切换实现,方便大家理解数据源切换的原理。今天我们来介绍一个开源的数据源切换框架,是baomidou 旗下和 Mybatis-plus 同级的开源框架:dynamic-datasource-spring-boot-starter。

1. 简介

dynamic-datasource-spring-boot-starter 是一个基于springboot的快速集成多数据源的启动器。

其支持 Jdk 1.7+, SpringBoot 1.5.x 2.x.x 3.x.x
JPA用户不建议使用,JPA自带事务,无法连续切库。

2. 使用

下面基于SpringBoot2 做演示。

1.pom.xml

<dependency><groupId>com.baomidou</groupId><artifactId>dynamic-datasource-spring-boot-starter</artifactId><version>4.3.1</version>
</dependency>

2.application.yml

spring:datasource:dynamic:primary: master #设置默认的数据源或者数据源组,默认值即为masterstrict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源datasource:master:url: jdbc:mysql://192.168.183.128:3306/userusername: rootpassword: 123456slave_1:url: jdbc:mysql://192.168.183.128:3307/userusername: rootpassword: 123456slave_2:url: jdbc:mysql://192.168.183.128:3308/userusername: rootpassword: 123456

参数说明:

以上会配置一个默认库master,一个组slave下有两个子库slave_1,slave_2

后续我们会使用AOP注解的方式指定数据源。

例如:@DS("master")、@DS("slave")

  1. 配置文件所有以下划线 _ 分割的数据源 首部 即为组的名称,相同组名称的数据源会放在一个组下。
  2. 切换数据源可以是组名,也可以是具体数据源名称。组名则切换时采用负载均衡算法切换。

例如:当我们使用@DS("slave")时,指定了组名  “slave”,那么它会采用负载均衡算法自动切换数据源。

因为我们后续希望实现Mysql主从读写分离,所有写操作走master数据库,所有读操作走slave从数据库。

3. 使用 @DS 切换数据源。

@Service
public class UserServiceImpl implements UserService {@Autowiredprivate UserMapper userMapper;@Overridepublic void insert(User user) {userMapper.insert(user);}@Override@DS("slave_1")public List<User> selectAll() {userMapper.selectAll();}@Override@DS("slave")public User selectById(Integer id) {return userMapper.selectById(id);}
}

说明:

insert() 方法没有加@DS,默认使用master数据库。

selectAll() 方法指定使用数据源slave_1

selectById() 使用slave组,自动负载均衡查询。

注:@DS 可以注解在方法上或类上,同时存在就近原则 方法上注解 优先于 类上注解

若要实现Mysql主从自动复制,还需要配置mysql主从复制,详情参考博客:

ShardingSphere5:Mysql主从集群搭建、读写分离_shardingsphere mysql读写分离-CSDN博客

其中SpringBoot配置 ShardingSphere5 这一块不用管,Mysql主从集群搭建是不变的。

4.其他实现

3. 底层原理

1. SpringBoot自动配置

我们找到 DynamicDataSourceAutoConfiguration.class。 这是框架的自动配置类。

这一段是从我们配置的application.yml 读取并设置相关属性,也就是我们配置的数据源信息。

具体的话,是赋值给 DynamicRoutingDataSource 这个对象。

2. 扫描@DS注解

这是 DynamicDataSourceAnnotationInterceptor 的 invoke 方法,典型的AOP。

在所有加了@DS的方法上,

1. 当执行目标方法的时候,会先获取到@DS("XXX")中数据源的名称,dsKey。

2. 然后再把dsKey 存到ThreadLocal中,也就是图中的DynamicDataSourceContextHolder。

3. 最后再开始执行目标方法。

3. DynamicRoutingDataSource

回到我们之前自动配置里说的 DynamicRoutingDataSource

观察 DynamicRoutingDataSource 的继承关系链,发现它实现了Spring的 DataSource 和 InitializingBean 接口。

这和我们上一篇博客手动实现数据源切换的思路是一样的。

在 DynamicRoutingDataSource 里,determineDataSource 从 ThreadLocal 里 获取到指定数据源名称

最后通过名称返回对应的DataSource数据源。

对比上一篇博客,

SpringBoot 手动实现动态切换数据源 DynamicSource (上)-CSDN博客

其实思路大差不差,只不过 dynamic-datasource-spring-boot-starter 更加完善,增加了AOP注解功能。

4. 无注解切换数据源

1. 自定义切面,结合 DynamicDatasourceNamedInterceptor ,对于所有以 select 方法开头的,设置使用 slave 数据源, 对于add、update、delete 开头的使用 master 数据源。

2. 自定义 Mybatis 拦截器,对于所有的写操作使用 master 数据源,所有读操作使用 slave 数据源。(即:把数据源标识写入 DynamicDataSourceContextHolder 中)。

3. 其他场景:SaaS多租户系统下,每个租户使用独立的数据库,那么可以要求前端携带请求头 “dsKey”。配置自定义拦截器,拦截请求,把dsKey 写入 DynamicDataSourceContextHolder。

今天的分享就到这里。

我是此林,关注我吧,带你看不一样的世界!

相关文章:

SpringBoot 手动实现动态切换数据源 DynamicSource (中)

大家好&#xff0c;我是此林。 SpringBoot 手动实现动态切换数据源 DynamicSource &#xff08;上&#xff09;-CSDN博客 在上一篇博客中&#xff0c;我带大家手动实现了一个简易版的数据源切换实现&#xff0c;方便大家理解数据源切换的原理。今天我们来介绍一个开源的数据源…...

y3编辑器教学5:触发器2 案例演示

文章目录 一、探索1.1 ECA1.1.1 ECA的定义1.1.2 使用触发器实现瞬间移动效果 1.2 变量1.2.1 什么是变量1.2.2 使用变量存储碎片收集数量并展现 1.3 if语句&#xff08;魔法效果挂接&#xff09;1.3.1 地形设置1.3.2 编写能量灌注逻辑1.3.3 编写能量灌注后&#xff0c;实现传送逻…...

数值分析——插值法(二)

文章目录 前言一、Hermite插值1.两点三次Hermite插值2.两点三次Hermite插值的推广3.非标准型Hermite插值 二、三次样条插值1.概念2.三弯矩方程 前言 之前写过Lagrange插值与Newton插值法的内容&#xff0c;这里介绍一些其他的插值方法&#xff0c;顺便复习数值分析. 一、Hermi…...

杨振宁大学物理视频中黄色的字,c#写程序去掉

先看一下效果&#xff1a;&#xff08;还有改进的余地&#xff09; 写了个程序消除杨振宁大学物理中黄色的字 我的方法是笨方法&#xff0c;也比较刻板。 1&#xff0c;首先想到&#xff0c;把屏幕打印下来。c#提供了这样一个函数&#xff1a; Bitmap bmp new Bitmap(640, 48…...

uni-app 设置缓存过期时间【跨端开发系列】

&#x1f517; uniapp 跨端开发系列文章&#xff1a;&#x1f380;&#x1f380;&#x1f380; uni-app 组成和跨端原理 【跨端开发系列】 uni-app 各端差异注意事项 【跨端开发系列】uni-app 离线本地存储方案 【跨端开发系列】uni-app UI库、框架、组件选型指南 【跨端开…...

微信小程序base64图片与临时路径互相转换

1、base64图片转临时路径 /*** 将base64图片转临时路径* param {*} dataurl* param {*} filename* returns*/base64ImgToFile(dataurl, filename "file") {const base64 dataurl; // base64码const time new Date().getTime();const imgPath wx.env.USER_DATA_P…...

蓝桥杯刷题——day2

蓝桥杯刷题——day2 题目一题干题目解析代码 题目二题干解题思路代码 题目一 题干 三步问题。有个小孩正在上楼梯&#xff0c;楼梯有n阶台阶&#xff0c;小孩一次可以上1阶、2阶或3阶。实现一种方法&#xff0c;计算小孩有多少种上楼梯的方式。结果可能很大&#xff0c;你需要…...

5.删除链表的倒数第N个节点

19.删除链表的倒数第N个节点 题目&#xff1a; 19. 删除链表的倒数第 N 个结点 - 力扣&#xff08;LeetCode&#xff09; 分析&#xff1a; 要删除倒数第几个节点&#xff0c;那么我们需要怎么做呢&#xff1f;我们需要定义两个指针&#xff0c;快指针和慢指针&#xff0c;…...

自己总结:selenium高阶知识

全篇大概10000字&#xff08;含代码&#xff09;&#xff0c;建议阅读时间30min 一、等待机制 如果有一些内容是通过Ajax加载的内容&#xff0c;那就需要等待内容加载完毕才能进行下一步操作。 为了避免人为操作等待&#xff0c;会遇到的问题&#xff0c; selenium将等待转换…...

前端怎么预览pdf

1.背景 后台返回了一个在线的pdf地址&#xff0c;需要我这边去做一个pdf的预览&#xff08;需求1&#xff09;&#xff0c;并且支持配置是否可以下载&#xff08;需求2&#xff09;&#xff0c;需要在当前页就能预览&#xff08;需求3&#xff09;。之前我写过一篇预览pdf的文…...

activemq 的安装部署

下载 https://activemq.apache.org/components/classic/download/# 在/opt目录下载 wget https://dlcdn.apache.org//activemq/5.18.6/apache-activemq-5.18.6-bin.tar.gz解压 tar -zxvf apache-activemq-5.18.6-bin.tar.gz配置java环境 vim /opt/apache-activemq-5.18.6/b…...

【H3CNE邓方鸣】配置链路聚合+2024.12.11

文章目录 链路聚合作用负载分担分类静态聚合动态聚合 链路聚合作用 定义&#xff1a;把连接到统一交换机上的多个物理端口捆绑为一个逻辑端口 增加链路带宽&#xff1a;聚合组内只要还有物理端口存活&#xff0c;链路就不会中断 提供链路可靠性&#xff1a;避免了STP计算&…...

C语言 学习 日志 递归函数 2024/12/12

C语言 学习 日志 递归函数 介绍: 初始调用&#xff1a;递归函数被首次调用。递归调用&#xff1a;递归函数在其定义中调用自身&#xff0c;创建新的栈帧。基本情况检查&#xff1a;每次递归调用时&#xff0c;检查是否满足基本情况。如果满足&#xff0c;返回结果并开始回溯。…...

【Ubuntu】使用ip link工具创建虚拟局域网并配置?

&#x1f98b;&#x1f98b;&#x1f98b;如何使用ip link工具创建虚拟局域网&#xff1f; sudo ip link add link enx888bd66b7000 name enx.120 type vlan id 120 上述命令使用ip link工具在Linux系统中创建了一个新的虚拟局域网&#xff08;VLAN&#xff09;接口&#xff0c…...

flink sink kafka的事务提交现象猜想

现象 查看flink源码时 sink kafka有事务提交机制&#xff0c;查看源码发现是使用两阶段提交策略&#xff0c;而事务提交是checkpoint完成后才执行&#xff0c;那么如果checkpoint设置间隔时间比较长时&#xff0c;事务未提交之前&#xff0c;后端应该消费不到数据&#xff0c…...

网络原理03

回顾 应用层&#xff1a;应用程序&#xff0c;数据具体如何使用 传输层&#xff1a;关注起点和终点 网络层&#xff1a;关注路径规划 数据链路层&#xff1a;关注相邻节点的转发 物理层&#xff1a;硬件设备 应用层 应用程序 在应用层&#xff0c;很多时候&#xff0c;…...

每天40分玩转Django:简介和环境搭建

Django简介和环境搭建 一、课程概述 学习项目具体内容预计用时Django概念Django框架介绍、MVC/MTV模式、Django特点60分钟环境搭建Python安装、pip配置、Django安装、IDE选择45分钟创建项目项目结构、基本配置、运行测试75分钟实战练习创建个人博客项目框架60分钟 二、Djang…...

【蓝桥杯最新板】蓝桥杯嵌入式液晶上实现电子时钟

这几年蓝桥杯比赛比较适合学生技能学习&#xff0c;考虑板子功能&#xff0c;提出完成的任务。 要求在液晶完成如下图效果&#xff1a; 主要是实现液晶显示时钟和数字时钟&#xff0c;具体样式可以依据实际情况微调。 实现过程&#xff1a; 1.需要画圆&#xff08;外圆、内圆…...

【机器学习】基础知识:拟合度(Goodness of Fit)

拟合度概念及意义 拟合度&#xff08;Goodness of Fit&#xff09;是衡量统计模型对数据解释能力的指标&#xff0c;用于评价模型对观测数据的拟合效果。在回归分析、分类模型或其他预测模型中&#xff0c;拟合度是模型性能的重要衡量标准。 1. 拟合度的作用 拟合度的主要作用…...

使用Jackson库在Java应用程序中将Map对象转换为JSON数组字符串,以及反向操作

在现代Java应用程序中&#xff0c;特别是使用RESTful Web服务时&#xff0c;经常需要将Java对象转换为JSON格式&#xff0c;反之亦然。 当表示如用户管理系统中的用户列表这样的数据结构时&#xff0c;将Map转换为JSON数组字符串变得非常有用。在这个指南中&#xff0c;我们将…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

汽车生产虚拟实训中的技能提升与生产优化​

在制造业蓬勃发展的大背景下&#xff0c;虚拟教学实训宛如一颗璀璨的新星&#xff0c;正发挥着不可或缺且日益凸显的关键作用&#xff0c;源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例&#xff0c;汽车生产线上各类…...

什么是库存周转?如何用进销存系统提高库存周转率?

你可能听说过这样一句话&#xff1a; “利润不是赚出来的&#xff0c;是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业&#xff0c;很多企业看着销售不错&#xff0c;账上却没钱、利润也不见了&#xff0c;一翻库存才发现&#xff1a; 一堆卖不动的旧货…...

如何为服务器生成TLS证书

TLS&#xff08;Transport Layer Security&#xff09;证书是确保网络通信安全的重要手段&#xff0c;它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书&#xff0c;可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

嵌入式学习笔记DAY33(网络编程——TCP)

一、网络架构 C/S &#xff08;client/server 客户端/服务器&#xff09;&#xff1a;由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序&#xff0c;负责提供用户界面和交互逻辑 &#xff0c;接收用户输入&#xff0c;向服务器发送请求&#xff0c;并展示服务…...

并发编程 - go版

1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

Python Einops库:深度学习中的张量操作革命

Einops&#xff08;爱因斯坦操作库&#xff09;就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库&#xff0c;用类似自然语言的表达式替代了晦涩的API调用&#xff0c;彻底改变了深度学习工程…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋

随着工业以太网的发展&#xff0c;其高效、便捷、协议开放、易于冗余等诸多优点&#xff0c;被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口&#xff0c;具有实时性、开放性&#xff0c;使用TCP/IP和IT标准&#xff0c;符合基于工业以太网的…...

9-Oracle 23 ai Vector Search 特性 知识准备

很多小伙伴是不是参加了 免费认证课程&#xff08;限时至2025/5/15&#xff09; Oracle AI Vector Search 1Z0-184-25考试&#xff0c;都顺利拿到certified了没。 各行各业的AI 大模型的到来&#xff0c;传统的数据库中的SQL还能不能打&#xff0c;结构化和非结构的话数据如何和…...