springboot+dynamicDataSource动态添加切换数据源方式

使用 Spring Boot,可以动态添加切换数据源,需要用到Spring JDBC模块中的 AbstractRoutingDataSource 类和 DynamicDataSourceHolder 维护一个存储当前使用的数据源 key 的 ThreadLocal 对象。步骤如下:

导入依赖

首先,在 pom.xml 中导入 Spring Boot 和 Spring JDBC 的依赖。

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

定义数据源

其次,在 application.yml 中定义数据源。

spring:
  datasource:
    default:
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8
      username: root
      password: root
    db1:
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://localhost:3306/db1?useUnicode=true&characterEncoding=UTF-8
      username: root
      password: root
    db2:
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://localhost:3306/db2?useUnicode=true&characterEncoding=UTF-8
      username: root
      password: root

定义动态数据源

public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DynamicDataSourceHolder.getDataSourceKey();
    }
}

维护当前使用数据源的 key

public class DynamicDataSourceHolder {
    private static final ThreadLocal<String> dataSourceKey = new InheritableThreadLocal<>();

    public static void setDataSourceKey(String key) {
        dataSourceKey.set(key);
    }

    public static String getDataSourceKey() {
        return dataSourceKey.get();
    }

    public static void clearDataSourceKey() {
        dataSourceKey.remove();
    }
}

配置动态数据源

@Configuration
public class DataSourceConfig {
    @Bean
    @ConfigurationProperties("spring.datasource")
    public DataSource defaultDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties("spring.datasource.db1")
    public DataSource db1DataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties("spring.datasource.db2")
    public DataSource db2DataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    public DynamicDataSource dynamicDataSource() {
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("default", defaultDataSource());
        targetDataSources.put("db1", db1DataSource());
        targetDataSources.put("db2", db2DataSource());

        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        dynamicDataSource.setTargetDataSources(targetDataSources);
        dynamicDataSource.setDefaultTargetDataSource(defaultDataSource());

        return dynamicDataSource;
    }

    @Bean
    public SqlSessionFactoryBean sqlSessionFactory(DynamicDataSource dynamicDataSource) throws Exception {
        SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(dynamicDataSource);

        return sqlSessionFactory;
    }
}

上述代码中,@ConfigurationProperties("spring.datasource") 表示读取 yml 配置文件中的 spring.datasource 参数,这里将 default 数据源的信息读入 DataSource 中,其他两个数据源同理。DynamicDataSource 类是继承了 Spring JDBC 中的 AbstractRoutingDataSource 类,它会调用 DynamicDataSourceHolder 中的 getDataSourceKey() 方法获取当前数据源 key,然后根据这个 key 从 targetDataSources 中取出对应的数据源。

测试

为了方便测试,我们添加 Controller 和 Service。

@RestController
@RequestMapping("/user")
public class UserController {
    @Autowired
    private UserService userService;

    @GetMapping("/{id}")
    public User findById(@PathVariable Integer id, @RequestParam String db) {
        DynamicDataSourceHolder.setDataSourceKey(db);
        User user = userService.findById(id);
        DynamicDataSourceHolder.clearDataSourceKey();

        return user;
    }
}

@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;

    public User findById(Integer id) {
        return userMapper.findById(id);
    }
}

@Mapper
public interface UserMapper {
    User findById(Integer id);
}

这个示例中,我们为 Controller 增加了一个请求参数 db,它的值可以是 default、db1 或 db2,为了测试是否切换了数据源,我们在 findById() 方法中调用 DynamicDataSourceHolder.setDataSourceKey() 方法设置数据源 key,然后在调用 UserService.findById() 方法完成查询后,调用 DynamicDataSourceHolder.clearDataSourceKey() 方法清除数据源 key,这样就完成了数据源的切换。

$ curl http://localhost:8080/user/1?db=db1
{"id":1,"name":"User 1","age":20}
$ curl http://localhost:8080/user/2?db=db2
{"id":2,"name":"User 2","age":30}

根据访问地址中的 db 参数的值,会分别从 db1 和 db2 数据库中查询数据。

可以看到,使用 Spring Boot 实现动态添加切换数据源非常简单。

阅读剩余 71%

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:springboot+dynamicDataSource动态添加切换数据源方式 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • 什么是对象终结器?

    对象终结器(Finalizer)是.NET框架中用于清理未经处理的对象的机制,确保在对象被销毁之前,能够执行一些特定的清理工作,如释放资源、关闭文件等。本文将对对象终结器的使用进行详细讲解,并提供两个示例说明。 对象终结器的使用 要使用对象终结器,需要定义一个名为Finalize的方法。这个方法的语法如下: ~MyClass() { // 清理代码 } 在这…

    Java 2023年5月11日
    00
  • springboot整合shardingjdbc实现分库分表最简单demo

    下面是一份完整的SpringBoot整合ShardingJDBC实现分库分表最简单demo的攻略: 一、前置条件 掌握SpringBoot和Maven的基础及配置方式; 了解什么是ShardingJDBC以及其分库分表的实现原理; 准备好使用的数据库及其账号密码。 二、添加依赖 在Maven的pom.xml文件中添加以下依赖: <dependency&…

    Java 2023年5月20日
    00
  • 两种java文件上传实例讲解

    下面是详细讲解“两种java文件上传实例讲解”的攻略: 一、基于Spring MVC框架的文件上传实例 1. 在Maven项目配置中添加以下依赖: <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</…

    Java 2023年5月19日
    00
  • Spring引入外部属性文件配置数据库连接的步骤详解

    首先需要说明的是 Spring 引入外部属性文件配置数据库连接的过程非常简单,只需要遵循下面的几个步骤即可。 1. 创建属性文件 首先需要在项目的某个目录下创建一个属性文件,比如我们创建一个 db.properties 文件,用于存储数据库连接的相关信息,示例代码如下: jdbc.driver=com.mysql.jdbc.Driver jdbc.url=j…

    Java 2023年6月16日
    00
  • java安全编码指南之:声明和初始化说明

    以下是关于“Java安全编码指南之:声明和初始化说明”的完整攻略。 标识声明和初始化 何时使用 在使用 Java 进行编程时,声明和初始化变量是非常重要的基本技能。正确的声明和初始化变量可以帮助我们避免许多常见的安全问题,例如悬挂指针和缓冲区溢出。 如何做到 使用关键字 final 使用关键字 final 可以确保变量的值在声明后不会再次更改。 示例1: f…

    Java 2023年5月20日
    00
  • gateway、webflux、reactor-netty请求日志输出方式

    为了让大家更好地了解 “gateway、webflux、reactor-netty请求日志输出方式”,我将分别讲解这三个主题,并提供相应的示例代码,在此之前,请确保已经安装好了Java环境,并了解基本的Spring Boot框架。 Gateway请求日志输出方式 Gateway是Spring Cloud的组件之一,可以将多个微服务组合起来作为一个整体对外提供…

    Java 2023年5月20日
    00
  • Apache Hudi结合Flink的亿级数据入湖实践解析

    下面我来详细讲解一下Apache Hudi结合Flink的亿级数据入湖实践解析的完整攻略。 概述 本文主要介绍如何使用Apache Hudi和Flink实现亿级数据的入湖操作。Hudi是一个可靠的增量数据处理框架,适用于在Apache Spark等大数据处理框架上进行大数据增量计算。而Flink则是一个分布式流处理框架,具有高吞吐量和低延迟的特点。将两者结合…

    Java 2023年5月20日
    00
  • Java实现字符串切割的方法详解

    Java实现字符串切割的方法详解 在Java开发中,经常需要将一个字符串按照特定规则进行切割,切割后的字符串可以使用来进行各种操作。本文就 Java 实现字符串切割的方法进行详细的讲解 1、使用 split() 方法 Java内置的String类中,提供了 split() 方法,该方法可以实现对字符串按照特定规则进行切割,返回一个字符串数组。下面是使用 sp…

    Java 2023年5月26日
    00
合作推广
合作推广
分享本页
返回顶部