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

SpringBoot如何实现动态数据源?

在Spring Boot中实现动态数据源主要涉及到创建和管理不同的数据源,并在运行时根据需要切换。这可以通过编程方式配置Spring的AbstractRoutingDataSource来完成。下面我会逐步介绍如何实现动态数据源,并给出代码示例。

第1步:添加依赖

首先,你需要在pom.xml文件中添加Spring Boot和数据库相关的依赖。以MySQL为例,你需要添加以下依赖:

<dependencies><!-- Spring Boot Starter Data JPA --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jpa</artifactId></dependency><!-- MySQL Connector --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><!-- Spring Boot Starter Web --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency>
</dependencies>

第2步:配置数据源

创建一个配置类来配置多个数据源。首先,定义每个数据源的配置,并使用Spring的@ConfigurationProperties来绑定配置属性。

@Configuration
public class DataSourceConfig {@Bean@ConfigurationProperties("app.datasource.master")public DataSource masterDataSource() {return DataSourceBuilder.create().build();}@Bean@ConfigurationProperties("app.datasource.slave")public DataSource slaveDataSource() {return DataSourceBuilder.create().build();}@Primary@Beanpublic DataSource dynamicDataSource() {Map<Object, Object> targetDataSources = new HashMap<>();targetDataSources.put("master", masterDataSource());targetDataSources.put("slave", slaveDataSource());RoutingDataSource routingDataSource = new RoutingDataSource();routingDataSource.setDefaultTargetDataSource(masterDataSource());routingDataSource.setTargetDataSources(targetDataSources);return routingDataSource;}
}

第3步:实现AbstractRoutingDataSource

接下来,你需要实现AbstractRoutingDataSource,以便根据当前上下文确定应使用哪个数据源。

public class RoutingDataSource extends AbstractRoutingDataSource {@Overrideprotected Object determineCurrentLookupKey() {return DataSourceContext.getCurrentDataSource();}
}

第4步:上下文持有器

创建一个DataSourceContext类来持有当前请求的数据源标识。

public class DataSourceContext {private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();public static void setCurrentDataSource(String dataSourceType) {contextHolder.set(dataSourceType);}public static String getCurrentDataSource() {return contextHolder.get();}public static void clear() {contextHolder.remove();}
}

第5步:使用切面来切换数据源

你可以使用Spring AOP在方法执行前动态切换数据源。下面是一个示例:

@Aspect
@Component
public class DataSourceAspect {@Before("@annotation(targetDataSource)")public void switchDataSource(TargetDataSource targetDataSource) {DataSourceContext.setCurrentDataSource(targetDataSource.value());}@After("@annotation(targetDataSource)")public void restoreDataSource(TargetDataSource targetDataSource) {DataSourceContext.clear();}
}

其中TargetDataSource是一个自定义注解,用来在方法上标记需要切换的数据源。

@Target({ ElementType.METHOD, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface TargetDataSource {String value();
}

第6步:配置application.properties

application.properties中配置你的数据源:

app.datasource.master.jdbc-url=jdbc:mysql://localhost:3306/masterdb
app.datasource.master.username=root
app.datasource.master.password=passapp.datasource.slave.jdbc-url=jdbc:mysql://localhost:3306/slavedb
app.datasource.slave.username=root
app.datasource.slave.password=pass

通过以上步骤,你可以在Spring Boot应用中实现动态数据源,根据不同的需求切换到不同的数据库。这种方式特别适合于读写分离和多租户场景。

7、补充

实际使用中,偏业务的代码往往是根据业务相关ID做计算后放入DataSourceContext数据的,也就是同一个Method,不同的租户/用户使用的数据源可能是不一样的,这才更符合多租户系统的需求。而偏功能的系统,它的Method才有可能是固定的数据源(注解指定)。因此多租户的系统请求过来,我们可以通过在过滤器或者全局拦截器里计算值,然后写数据。

相关文章:

SpringBoot如何实现动态数据源?

在Spring Boot中实现动态数据源主要涉及到创建和管理不同的数据源&#xff0c;并在运行时根据需要切换。这可以通过编程方式配置Spring的AbstractRoutingDataSource来完成。下面我会逐步介绍如何实现动态数据源&#xff0c;并给出代码示例。 第1步&#xff1a;添加依赖 首先&…...

win10安装mysql8.0+汉化

一、官网安装 MySQL 1. 在mysql官网进行下载页面 2. 下滑页面&#xff0c;选择 MySQL community download 3.下载windows版本 4.选择第二个download 5.不用登陆&#xff0c;no thanks&#xff0c;just start my download. 6.下载 二、安装 1. 双击安装 2. 选 Full->next 3…...

全网最全的Postman接口自动化测试!

该篇文章针对已经掌握 Postman 基本用法的读者&#xff0c;即对接口相关概念有一定了解、已经会使用 Postman 进行模拟请求的操作。 当前环境&#xff1a; Window 7 - 64 Postman 版本&#xff08;免费版&#xff09;&#xff1a;Chrome App v5.5.3 不同版本页面 UI 和部分…...

Spring:了解@Import注解的三种用法

一、前言 在 Spring 框架中&#xff0c;Import 注解用于导入配置类&#xff0c;使得你可以在一个配置类中引入另一个或多个配置类&#xff0c;从而实现配置的模块化。这对于组织大型应用程序的配置非常有用&#xff0c;因为它允许你将配置分散到多个类中&#xff0c;然后再将它…...

简要介绍三大脚本语言 Shell、Python 和 Lua

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 脚本语言是一种用于自动化操作系统任务和应用程序功能的编程语言。它们通常用于编写小到中等规模的程序&#xff0c;以提高任务执行的速度和效率。在众多脚本语言中&#xff0c;Shell、Python 和 Lua 是…...

第 397 场 LeetCode 周赛题解

A 两个字符串的排列差 模拟&#xff1a;遍历 s s s 记录各字符出现的位置&#xff0c;然后遍历 t t t 计算排列差 class Solution {public:int findPermutationDifference(string s, string t) {int n s.size();vector<int> loc(26);for (int i 0; i < n; i)loc[s…...

文件存储解决方案-阿里云OSS

文章目录 1.菜单分级显示问题1.问题引出1.苹果灯&#xff0c;放到节能灯下面也就是id大于1272.查看菜单&#xff0c;并没有出现苹果灯3.放到灯具下面id42&#xff0c;就可以显示 2.问题分析和解决1.判断可能出现问题的位置2.找到递归返回树形菜单数据的位置3.这里出现问题的原因…...

基于Java的飞机大战游戏的设计与实现(论文 + 源码)

关于基于Java的飞机大战游戏.zip资源-CSDN文库https://download.csdn.net/download/JW_559/89313362 基于Java的飞机大战游戏的设计与实现 摘 要 现如今&#xff0c;随着智能手机的兴起与普及&#xff0c;加上4G&#xff08;the 4th Generation mobile communication &#x…...

Vue路由开启步骤

1.在控制台输入命令 //控制台下载安装npm add vue-router3.6.5 2.在main.js下导入并注册组件 import Vue from vue import App from ./App.vue//控制台下载安装npm add vue-router3.6.5 //导入 import VueRouter from "vue-router";//注册 Vue.use(VueRouter) con…...

【碎片知识】2024_05_15

char int long float double运算的时候是从低转到高的&#xff0c;表达式的类型会自动提升或者转 换为参与表达式求值的最上级类型. 关于代码的说法正确的是&#xff08; &#xff09; #include <stdio.h> int main() {int x -1;unsigned int y 2;if (x > y){printf…...

彩虹聚合DNS管理系统

聚合DNS管理系统可以实现在一个网站内管理多个平台的域名解析&#xff0c;目前已支持的域名平台有&#xff1a;阿里云、腾讯云、华为云、西部数码、CloudFlare。本系统支持多用户&#xff0c;每个用户可分配不同的域名解析权限&#xff1b;支持API接口&#xff0c;支持获取域名…...

服务网格 SolarMesh v1.13 重磅发布

SolarMesh是行云创新推出的流量治理平台&#xff0c;它基于Istio&#xff0c;为部署在K8s集群上的应用提供全面的流量治理能力。 在之前的版本中&#xff0c;SolarMesh提供的能力有&#xff1a;流量视图&#xff0c;流量控制策略批量配置&#xff0c;API级别的流量数据采集和展…...

三大平台直播视频下载保存方法

终于解决了视频号下载的问题&#xff0c;2024年5月15日亲测可用。 而且免费。 教程第二部分&#xff0c;有本地电脑无法下载的解决方案。 第一部分&#xff1a;使用教程&#xff08;正常&#xff09; 第1步&#xff1a;下载安装包 下载迅雷网盘搜索&#xff1a;大海福利合集…...

OpenAI GPT-4o - 介绍

本文翻译整理自&#xff1a; Hello GPT-4o https://openai.com/index/hello-gpt-4o/ 文章目录 一、关于 GPT-4o二、模型能力三、能力探索四、模型评估1、文本评价2、音频 ASR 性能3、音频翻译性能4、M3Exam 零样本结果5、视觉理解评估6、语言 tokenization 六、模型安全性和局限…...

QTreeView学习 branch 虚线设置

1、方法一&#xff1a; #include <QStyleFactory> ui.treeView->setStyle(QStyleFactory::create("windows")); 2、方法二&#xff1a; QString strtyle2 R"( QTreeView::branch:has-siblings:!adjoins-item { border-image: url(:/TreeViewDe…...

C++ 日志库 log4cpp 编译、压测及其范例代码 [全流程手工实践]

文章目录 一、 log4cpp官网二、下载三、编译1.目录结构如下2.configure 编译3.cmake 编译 四、测试五、压测源码及结果1.运行环境信息2.压测源码3.压测结果 文章内容&#xff1a;包含了对其linux上的完整使用流程&#xff0c;下载、编译、安装、测试用例尝试、以及一份自己写好…...

python数据处理与分析入门-pandas使用(4)

往期文章&#xff1a; pandas使用1pandas使用2pandas使用3 pandas使用技巧 创建一个DF对象 # 首先创建一个时间序列 dates pd.date_range(20180101, periods6) print(dates)# 创建DataFrame对象&#xff0c;指定index和columns标签 df pd.DataFrame(np.random.randn(6,4), …...

操作系统-单片机进程状态问题(三态模型问题)

例题&#xff1a;在单处理机计算机系统中有1台打印机、1台扫描仪&#xff0c;系统采用先来先服务调度算法。假设系统中有进程P1、P2、P3、P4&#xff0c;其中P1为运行状态&#xff0c;P2为就绪状态&#xff0c;P3等待打印机&#xff0c;P4等待扫描仪。此时&#xff0c;若P1释放…...

Linux文件:重定向底层实现原理(输入重定向、输出重定向、追加重定向)

Linux文件&#xff1a;重定向底层实现原理&#xff08;输入重定向、输出重定向、追加重定向&#xff09; 前言一、文件描述符fd的分配规则二、输出重定向&#xff08;>&#xff09;三、输出重定向底层实现原理四、追加重定向&#xff08;>>&#xff09;五、输入重定向…...

波搜索算法(WSA)-2024年SCI新算法-公式原理详解与性能测评 Matlab代码免费获取

​ 声明&#xff1a;文章是从本人公众号中复制而来&#xff0c;因此&#xff0c;想最新最快了解各类智能优化算法及其改进的朋友&#xff0c;可关注我的公众号&#xff1a;强盛机器学习&#xff0c;不定期会有很多免费代码分享~ 目录 原理简介 一、初始化阶段 二、全…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

测试微信模版消息推送

进入“开发接口管理”--“公众平台测试账号”&#xff0c;无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息&#xff1a; 关注测试号&#xff1a;扫二维码关注测试号。 发送模版消息&#xff1a; import requests da…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

自然语言处理——循环神经网络

自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元&#xff08;GRU&#xff09;长短期记忆神经网络&#xff08;LSTM&#xff09…...

GruntJS-前端自动化任务运行器从入门到实战

Grunt 完全指南&#xff1a;从入门到实战 一、Grunt 是什么&#xff1f; Grunt是一个基于 Node.js 的前端自动化任务运行器&#xff0c;主要用于自动化执行项目开发中重复性高的任务&#xff0c;例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...

基于SpringBoot在线拍卖系统的设计和实现

摘 要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统&#xff0c;主要的模块包括管理员&#xff1b;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...

(一)单例模式

一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...

Linux 下 DMA 内存映射浅析

序 系统 I/O 设备驱动程序通常调用其特定子系统的接口为 DMA 分配内存&#xff0c;但最终会调到 DMA 子系统的dma_alloc_coherent()/dma_alloc_attrs() 等接口。 关于 dma_alloc_coherent 接口详细的代码讲解、调用流程&#xff0c;可以参考这篇文章&#xff0c;我觉得写的非常…...

Vue3中的computer和watch

computed的写法 在页面中 <div>{{ calcNumber }}</div>script中 写法1 常用 import { computed, ref } from vue; let price ref(100);const priceAdd () > { //函数方法 price 1price.value ; }//计算属性 let calcNumber computed(() > {return ${p…...

开疆智能Ethernet/IP转Modbus网关连接鸣志步进电机驱动器配置案例

在工业自动化控制系统中&#xff0c;常常会遇到不同品牌和通信协议的设备需要协同工作的情况。本案例中&#xff0c;客户现场采用了 罗克韦尔PLC&#xff0c;但需要控制的变频器仅支持 ModbusRTU 协议。为了实现PLC 对变频器的有效控制与监控&#xff0c;引入了开疆智能Etherne…...