SpringBoot实现【动态数据源配置】这一篇就够了

2024-04-28 18:04

本文主要是介绍SpringBoot实现【动态数据源配置】这一篇就够了,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

实现动态数据源配置

  • 0. 排除数据源的自动装配
  • 1. yml配置多个数据源信息
  • 2. 使用ThreadLocal,保存数据源名称供下游业务使用
  • 3. 定义数据源类,继承AbstractRoutingDataSource
  • 4. 定义配置类读取数据源信息,设置数据源对象属性
  • 5. 定义自定义数据源注解
  • 6. 定义切面,设置数据源名到ThreadLocal中
  • 7. 使用动态数据源

0. 排除数据源的自动装配

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})

1. yml配置多个数据源信息

spring:datasource:master:driverClassName: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.124.200:3306/monitorusername: rootpassword: rootsalve:driverClassName: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://192.168.124.201:3306/monitorusername: rootpassword: root

2. 使用ThreadLocal,保存数据源名称供下游业务使用

public class DataSourceContextHolder {private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();// 设置数据源名public static void setDataSource(String dbName) {contextHolder.set(dbName);}// 获取数据源名public static String getDataSource() {return (contextHolder.get());}// 清除数据源名public static void clearDataSource() {contextHolder.remove();}
}

3. 定义数据源类,继承AbstractRoutingDataSource

public class DynamicDataSource extends AbstractRoutingDataSource {@Overrideprotected Object determineCurrentLookupKey() {return DataSourceContextHolder.getDataSource();}}

4. 定义配置类读取数据源信息,设置数据源对象属性

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

5. 定义自定义数据源注解

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface DS {String value() default "master";
}

6. 定义切面,设置数据源名到ThreadLocal中

@Component
@Aspect
public class DynamicDataSourceAspect {@Pointcut("@annotation(com.iteng.annotation.DS)")public void dynamicDataSourcePointCut() {}@Around("dynamicDataSourcePointCut()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {String dataSourceKey;// 类上的注解Class<?> aClass = joinPoint.getTarget().getClass();DS annotation = aClass.getAnnotation(DS.class);// 方法上的注解MethodSignature signature = (MethodSignature) joinPoint.getSignature();DS annotationMethod = signature.getMethod().getAnnotation(DS.class);if (Objects.nonNull(annotationMethod)) {dataSourceKey = annotationMethod.value();} else {dataSourceKey = annotation.value();}// 设置数据源DataSourceContextHolder.setDataSource(dataSourceKey);try {return joinPoint.proceed();}finally {DataSourceContextHolder.clearDataSource();}}
}

7. 使用动态数据源

@DS(value = "salve")
@GetMapping("/get")
public R getName(){// 数据库操作
}@DS
@PostMapping("/save")
public R sageName(){// 数据库操作
}

流程:

  • getName() 方法在执行之前,先执行对应的切面类,将“salve”这个数据源名称保存带ThreadLocal中
  • 然后执行getName() 方法,当遇到数据库操作时,首先要与数据库进行连接。
  • MyBatis 会先找 DataSource 的实现类,因为 DataSource 有getConnection() 方法。
  • 继承了 AbstractRoutingDataSource 的 DynamicDataSource 会被找到。
  • 然后执行 DynamicDataSource 中的 determineTargetDataSource 方法,即确定 AbstractRoutingDataSource 中 Map 对应的Key,然后获取对应的数据源对象。
  • 进行数据库连接。

这篇关于SpringBoot实现【动态数据源配置】这一篇就够了的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/943889

相关文章

我碰到的Java实习面试题集合

面试公司:今日头条,阿里巴巴,远景能源,腾讯,天数,上海星环科技。 一、Java基础 ArrayList和LinkedList的区别?(链表和数组的优缺点) 答:ArrayList是一个动态的数组结构,而LinkedList是双向链表结构;存取数据的时候,ArrayList更适合按位随机存取,而LinkedList更适合顺序读存取;插入/删除数据时,ArrayList的开销就比Linked

NAT技术总结与双向NAT配置案例

NAT的转换方式: 1.静态转换:固定的一对一IP地址映射。 interface GigabitEthernet0/0/1 ip address 122.1.2.24 nat static global 122.1.2.1 inside 192.168.1.1 #在路由器出接口 公网地址 私网地址。 2.动态转换:Basic NAT nat address-group 1 122.1.2.1 1

Android 应用开发-实现将公共存储空间内的文件复制到应用的私用存储空间中

一、前言 几个月前,我用Android Studio给公司销售部门的同事开发了一款手机app,让同事们用自己的手机就能进行商品的扫码盘点操作,帮他们提高了工作效率,他们用了一段时间,反映还不错。不过前几天,销售部门的同事找到我,说近期公司新增了一些商品,用我的这款软件无法正常扫码这些新商品,希望我能解决问题。    这个问题的产生原因是,因为我的能力和资源有限,开发的这款手机app只是一

Vue3:分类管理综合案例实现

综合案例 实现分类管理功能 路由 在main.js中引入router 访问根路径’/'后跳转到布局容器 加载布局容器后重定向到’/nav/manage’ 加载我们需要的组件 这样可以在布局容器中切换功能模块时,只对需要修改的组件进行重新加载 const router = createRouter({history: createWebHistory(import.meta.en

1、什么是 Java 虚拟机?为什么 Java 被称作是“平台无关的编程语言”?

本文为转载,好记性不如烂笔头 1、什么是 Java 虚拟机?为什么 Java 被称作是“平台无关的编程语言”? Java 虚拟机是一个可以执行 Java 字节码的虚拟机进程。Java 源文件被编译成能被 Java 虚拟机执行的字节码文件。 Java 被设计成允许应用程序可以运行在任意的平台,而不需要程序员为每一个平台单独重写或者是重新编译。Java 虚拟机让这个变为可能,因为它知道底层硬件平

JVM内存结构 —— Java内存模型 ——Java对象模型

注明:转载. JVM内存结构、Java内存模型和Java对象模型,这就是三个截然不同的概念,但是很多人容易弄混。

JVM原理及性能调优

注明:转载文章。好记性不如烂笔头呀~ 一、什么是JVM     JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。 Java语言的一个非常重要的特点就是与平台的无关性。而使用Java虚拟机是实现这一特点的关键。一般的高级语言如果要在不同的平台上运行,至少

JavaScript-输入输出语句

输出语句 document.write(' 输出的内容 ') 语法:document.write(' 输出的内容') 作用:内容会显示在网页上 如果输出的内容是标签,也会被解析为网页元素 代码: <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="wid

LeetCode算法题:11. 盛最多水的容器(Java)(双指针问题总结)

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 提示: n == height.length2 <= n <= 10^50 <= height[i] <= 10^4 解题思路: 定义两个指针

基于java的超级玛丽游戏的设计与实现(论文 + 源码)

Java的超级玛丽游戏.zip资源-CSDN文库https://download.csdn.net/download/JW_559/89313347 基于java的超级玛丽游戏的设计与实现 摘要 近年来,Java作为一种新的编程语言,以其简单性、可移植性和平台无关性等优点,得到了广泛地应用。J2SE称为Java标准版或Java标准平台。J2SE提供了标准的SDK开发平台。利用该平台可以开发J