SpringBoot如何在运行时动态添加数据源

此方案适用于解决springboot项目运行时动态添加数据源,非静态切换多数据源!!!

一、多数据源应用场景:

1.配置文件配置多数据源,如默认数据源:master,数据源1:salve1...,运行时动态切换已配置的数据源(master、salve1互相切换),无法在运行时动态添加配置文件中未配置的数据源。

2.配置一个默认数据源,运行时动态添加新数据源使用(本博客适用于此场景)

二、解决方案:

Spring提供了AbstractRoutingDataSource用于动态路由数据源,第一种场景继承AbstractRoutingDataSource类并覆写其protected abstract Object determineCurrentLookupKey()即可;

而第二种场景我们直接覆写protected DataSource determineTargetDataSource方法即可。原理可看下AbstractRoutingDataSource对应源码,比较简单,不做赘述。

直接上干货:

import com.fizz.utils.spring.SpringUtils;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import javax.sql.DataSource;

public class DynamicDataSource extends AbstractRoutingDataSource {

  private static final ThreadLocal<DataSource> dataSource = ThreadLocal.withInitial(() -> (DataSource) SpringUtils.getBean("defaultDataSource"));

  public static void setDataSource(DataSource dataSource) {
    DynamicDataSource.dataSource.set(dataSource);
  }

  public static DataSource getDataSource() {
    return DynamicDataSource.dataSource.get();
  }

  @Override
  protected Object determineCurrentLookupKey() {
    return null;
  }

  @Override
  protected DataSource determineTargetDataSource() {
    return getDataSource();
  }

  public static void clear() {
    DynamicDataSource.dataSource.remove();
  }
}
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
import java.util.HashMap;

@Configuration
public class DataSourceConfig {

  @Bean
  @ConfigurationProperties("spring.datasource.druid")
  public DataSource defaultDataSource() {
    return DruidDataSourceBuilder.create().build();
  }

  @Bean
  @Primary
  public DynamicDataSource dataSource() {
    DynamicDataSource dynamicDataSource = new DynamicDataSource();
    dynamicDataSource.setTargetDataSources(new HashMap<>());
    return dynamicDataSource;
  }
}

使用时直接调用DynamicDataSource.setDataSource(DataSource dataSource)方法即可,使用完后调用DynamicDataSource.clear()防止内存泄漏并重置默认数据源。

附上详细使用方法:

    DruidDataSource druidDataSource = new DruidDataSource();
    druidDataSource.setUrl("jdbc:mysql://localhost:3306/sys?characterEncoding=utf-8&useSSL=false&serverTimezone=UTC&useAffectedRows=true");
    druidDataSource.setUsername("root");
    druidDataSource.setPassword("root");
    DynamicDataSource.setDataSource(druidDataSource);
    此时数据源已切换到druidDataSource ,调用自己的业务方法即可。
    使用完后调用DynamicDataSource.clear();重置为默认数据源。

附上工具类SpringUtils :

import lombok.Getter;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

@Component
public final class SpringUtils implements ApplicationContextAware {

  @Getter
  private static ApplicationContext applicationContext;

  @Override
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    if (SpringUtils.applicationContext == null) {
      SpringUtils.applicationContext = applicationContext;
    }
  }

  public static <T> T getBean(Class<T> clazz) {
    return SpringUtils.applicationContext.getBean(clazz);
  }

  public static Object getBean(String name) {
    return SpringUtils.applicationContext.getBean(name);
  }

  public static String getProperty(String key) {
    return SpringUtils.applicationContext.getEnvironment().getProperty(key);
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • SpringBoot整合MyBatisPlus配置动态数据源的方法

    MybatisPlus特性 •无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑 •损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作 •强大的 CRUD 操作:内置通用 Mapper.通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求 •支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错 •支持多种数据库:支持 MySQL.MariaDB.Ora

  • 通过Spring Boot配置动态数据源访问多个数据库的实现代码

    之前写过一篇博客<Spring+Mybatis+Mysql搭建分布式数据库访问框架>描述如何通过Spring+Mybatis配置动态数据源访问多个数据库.但是之前的方案有一些限制(原博客中也描述了):只适用于数据库数量不多且固定的情况.针对数据库动态增加的情况无能为力. 下面讲的方案能支持数据库动态增删,数量不限. 数据库环境准备 下面一Mysql为例,先在本地建3个数据库用于测试.需要说明的是本方案不限数据库数量,支持不同的数据库部署在不同的服务器上.如图所示db_project_001.d

  • 使用Spring Boot快速构建基于SQLite数据源的应用

    为了提供一个单包易部署的服务器应用,考虑使用Spring Boot,因为其集成了Apache Tomcat,易于运行,免去绝大部分了服务器配置的步骤. 项目初始化 首先从mvn archetype:generate中选择 com.github.mkspcd:simple-webapp(或其他webapp模版) 模版生成项目结构. 更多关于maven请移步Maven - Users Centre 在pom.xml中添加parent来获取Spring Boot所需的最小依赖. <project xm

  • Spring Boot+Mybatis+Druid+PageHelper实现多数据源并分页的方法

    前言 本篇文章主要讲述的是SpringBoot整合Mybatis.Druid和PageHelper 并实现多数据源和分页.其中SpringBoot整合Mybatis这块,在之前的的一篇文章中已经讲述了,这里就不过多说明了.重点是讲述在多数据源下的如何配置使用Druid和PageHelper . Druid介绍和使用 在使用Druid之前,先来简单的了解下Druid. Druid是一个数据库连接池.Druid可以说是目前最好的数据库连接池!因其优秀的功能.性能和扩展性方面,深受开发人员的青睐. D

  • springboot v2.0.3版本多数据源配置方法

    本篇分享的是springboot多数据源配置,在从springboot v1.5版本升级到v2.0.3时,发现之前写的多数据源的方式不可用了,捕获错误信息如: 异常:jdbcUrl is required with driverClassName. 先来说下之前的多数据源配置如: spring: datasource: url: jdbc:sqlserver://192.168.122.111;DatabaseName=flight username: sa password: 1234.abc

  • 详解SpringBoot和Mybatis配置多数据源

    目前业界操作数据库的框架一般是 Mybatis,但在很多业务场景下,我们需要在一个工程里配置多个数据源来实现业务逻辑.在SpringBoot中也可以实现多数据源并配合Mybatis框架编写xml文件来执行SQL.在SpringBoot中,配置多数据源的方式十分便捷, 下面开始上代码: 在pom.xml文件中需要添加一些依赖 <!-- Spring Boot Mybatis 依赖 --> <dependency> <groupId>org.mybatis.spring.b

  • 通过springboot+mybatis+druid配置动态数据源

    一.建数据库和表 1.数据库demo1放一张user表 SET FOREIGN_KEY_CHECKS=0; -- ---------------------------- -- Table structure for user -- ---------------------------- DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NU

  • SpringBoot如何在运行时动态添加数据源

    此方案适用于解决springboot项目运行时动态添加数据源,非静态切换多数据源!!! 一.多数据源应用场景: 1.配置文件配置多数据源,如默认数据源:master,数据源1:salve1...,运行时动态切换已配置的数据源(master.salve1互相切换),无法在运行时动态添加配置文件中未配置的数据源. 2.配置一个默认数据源,运行时动态添加新数据源使用(本博客适用于此场景) 二.解决方案: Spring提供了AbstractRoutingDataSource用于动态路由数据源,第一种场景

  • ASP.NET Core MVC如何实现运行时动态定义Controller类型

    昨天有个朋友在微信上问我一个问题:他希望通过动态脚本的形式实现对ASP.NET Core MVC应用的扩展,比如在程序运行过程中上传一段C#脚本将其中定义的Controller类型注册到应用中,问我是否有好解决方案.我当时在外边,回复不太方便,所以只给他说了两个接口/类型:IActionDescriptorProvider和ApplicationPartManager.这是一个挺有意思的问题,所以回家后通过两种方案实现了这个需求.源代码从这里下载. 一.实现的效果 我们先来看看实现的效果.如下所

  • hadoop运行java程序(jar包)并运行时动态指定参数

    1)首先启动hadoop2个进程,进入hadoop/sbin目录下,依次启动如下命令 [root@node02 sbin]# pwd /usr/server/hadoop/hadoop-2.7.0/sbin sh start-dfs.sh sh start-yarn.sh jps 2)通过jps查看是否正确启动,确保启动如下6个程序 [root@node02 sbin]# jps 10096 DataNode 6952 NodeManager 9962 NameNode 10269 Second

  • mybatis创建一个或多个新用户 insert 字段和表名不确定时动态添加问题

    创建用户: /** * 创建一个或多个新用户 insert 字段和表名不确定时动态添加 */ @Test public void createAccount() { String lineColumn = ""; Map<String, Object> paramsMap = new HashMap<String, Object>(); Map<String, Object> dataMap = new HashMap<String, Obje

  • php运行时动态创建函数的方法

    本文实例讲述了php运行时动态创建函数的方法.分享给大家供大家参考.具体分析如下: 一般的语言函数必须定义了在运行,而php支持在运行时动态创建函数,下面是一个简单的范例,在运动时根据不同的条件创建函数$a <?php if (count($_POST) > 0) { $prepped = create_function('$a', 'return trim($_POST[$a]);'); } elseif (count($_GET) > 0) { $prepped = create_f

  • C#在运行时动态创建类型的实现方法

    本文实例讲述了C#在运行时动态创建类型的实现方法.是C#项目开发中很实用的技巧.分享给大家供大家参考.具体分析如下: 具体来说,C# 在运行时动态的创建类型是通过动态生成C#源代码,然后通过编译器编译成程序集的方式实现动态创建类型的. 主要功能代码如下: public static Assembly NewAssembly() { //创建编译器实例. provider = new CSharpCodeProvider(); //设置编译参数. cp = new CompilerParamete

  • Mybatis工具类JdbcTypeInterceptor运行时自动添加jdbcType属性

    JdbcTypeInterceptor 运行时自动添加 jdbcType 属性 拦截器签名 @Intercepts({ @Signature( type = ParameterHandler.class, method = "setParameters", args = {PreparedStatement.class}) }) 这类拦截器很少见,所以和其他拦截器(如分页插件)等搭配使用时不需要考虑顺序. 这个插件最适合的场景可能就是 Oracle 数据库,可以自动给所有方法添加 jd

  • 在Python运行时动态查看进程内部信息的方法

    接前两篇"运行时查看线程信息"的博客,我在想,既然我可以随时打印线程信息,那么我是不是可以随时打印进程内部的其它信息呢?比如,实时查看一些对象属性等,这样可以帮助我们在不重新启动应用程序的情况下就可以观察进程的执行状态.(这里暂时不考虑那些使用第三方库或工具的情况) 根据这个想法,查看了一下python的动态加载模块的方法,感觉这个想法还是比较靠谱,应该可以实现,所以动手写了个小测试验证了一把.(这里说明一下,只是验证性的,生产环境要使用的话,还是有不少问题需要考虑的.) 下面就是测试

  • Java运行时动态生成类实现过程详解

    最近一个项目中利用规则引擎,提供用户拖拽式的灵活定义规则.这就要求根据数据库数据动态生成对象处理特定规则的逻辑.如果手写不仅每次都要修改代码,还要每次测试发版,而且无法灵活根据用户定义的规则动态处理逻辑.所以想到将公共逻辑写到父类实现,将特定逻辑根据字符串动态生成子类处理.这就可以一劳永逸解决这个问题. 那就着手从Java如何根据字符串模板在运行时动态生成对象. Java是一门静态语言,通常,我们需要的class在编译的时候就已经生成了,为什么有时候我们还想在运行时动态生成class呢? 经过一

  • Java运行时动态生成对象的方法小结

    目录 一.利用JDK自带工具类实现 二.利用三方Jar包实现 三.利用Groovy脚本实现 最近一个项目中利用规则引擎,提供用户拖拽式的灵活定义规则.这就要求根据数据库数据动态生成对象处理特定规则的逻辑.如果手写不仅每次都要修改代码,还要每次测试发版,而且无法灵活根据用户定义的规则动态处理逻辑.所以想到将公共逻辑写到父类实现,将特定逻辑根据字符串动态生成子类处理.这就可以一劳永逸解决这个问题. 那就着手从Java如何根据字符串模板在运行时动态生成对象. Java是一门静态语言,通常,我们需要的c

随机推荐