Spring Boot 中 Druid 连接池与多数据源切换的方法

Spring Boot 中 Druid 连接池与多数据源切换的方法

在Spring Boot项目中,使用Druid连接池和进行多数据源切换是常见的需求,尤其是在需要读写分离、数据库分片等复杂场景下。本文将详细介绍如何在Spring Boot中配置Druid连接池并实现多数据源切换。

一、Druid连接池简介

Druid是阿里巴巴开源的一个数据库连接池,它不仅提供了高效的数据库连接管理,还具备监控、扩展等强大功能。Druid的主要特点包括:

  1. 监控能力:提供了详细的监控页面,可以实时监控SQL执行情况、连接池状态等。
  2. 扩展能力:支持多种数据库类型,并且可以通过插件机制进行扩展。
  3. 高效性能:通过一系列优化手段,提高了连接池的性能和稳定性。
二、Spring Boot中配置Druid连接池

在Spring Boot中配置Druid连接池相对简单,只需在pom.xml中添加相应的依赖,并在application.ymlapplication.properties中进行配置即可。

1. 添加依赖

pom.xml中添加Druid和Spring Boot Starter JDBC的依赖:

<dependencies>
    <!-- Druid连接池依赖 -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid-spring-boot-starter</artifactId>
        <version>1.2.6</version>
    </dependency>
    <!-- Spring Boot Starter JDBC依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
    <!-- MySQL驱动依赖 -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
    <!-- 其他依赖 -->
</dependencies>
2. 配置数据源

application.ymlapplication.properties中配置数据源信息。例如,在application.yml中:

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/db01?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF8&useSSL=false
    username: root
    password: 123456
    initial-size: 1
    min-idle: 1
    max-active: 20
    test-on-borrow: true
    # Druid其他配置
    druid:
      validation-query: SELECT 1 FROM DUAL
      test-while-idle: true
      time-between-eviction-runs-millis: 60000
      min-evictable-idle-time-millis: 300000
      pool-prepared-statements: true
      max-pool-prepared-statement-per-connection-size: 20
      stat-view-servlet:
        enabled: true
        url-pattern: /druid/*
      filter:
        stat:
          log-slow-sql: true
          slow-sql-millis: 2000
三、多数据源切换的实现

在Spring Boot中实现多数据源切换,可以通过继承AbstractRoutingDataSource类来实现。AbstractRoutingDataSource是Spring提供的一个抽象类,用于支持动态数据源切换。

1. 引入必要的依赖

除了Druid和Spring Boot Starter JDBC的依赖外,还需要引入MyBatis相关的依赖(如果项目使用MyBatis):

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.2.1</version>
</dependency>
2. 配置多数据源

application.yml中配置多个数据源的信息,例如:

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    datasource1:
      url: jdbc:mysql://127.0.0.1:3306/db01?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF8&useSSL=false
      username: root
      password: 123456
      initial-size: 1
      min-idle: 1
      max-active: 20
      test-on-borrow: true
      driver-class-name: com.mysql.cj.jdbc.Driver
    datasource2:
      url: jdbc:mysql://127.0.0.1:3306/db02?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF8&useSSL=false
      username: root
      password: 123456
      initial-size: 1
      min-idle: 1
      max-active: 20
      test-on-borrow: true
      driver-class-name: com.mysql.cj.jdbc.Driver
    datasource3:
      url: jdbc:mysql://127.0.0.1:3306/db03?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF8&useSSL=false
      username: root
      password: 123456
      initial-size: 1
      min-idle: 1
      max-active: 20
      test-on-borrow: true
      driver-class-name: com.mysql.cj.jdbc.Driver
3. 创建数据源配置类

创建数据源配置类,将每个数据源配置为Bean,并自动管理它们:

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

@Configuration
public class DynamicDataSourceConfig {

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.datasource1")
    public DataSource dataSource1() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.datasource2")
    public DataSource dataSource2() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.datasource3")
    public DataSource dataSource3() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    public DataSourceTransactionManager dataSourceTransactionManager1(@Qualifier("dataSource1") DataSource dataSource1) {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource1);
        return dataSourceTransactionManager;
    }

    @Bean
    public DataSourceTransactionManager dataSourceTransactionManager2(@Qualifier("dataSource2") DataSource dataSource2) {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource2);
        return dataSourceTransactionManager;
    }

    // 同理,可以创建dataSourceTransactionManager3等
}
4. 创建数据源上下文持有者

使用ThreadLocal维护当前线程的数据源信息:

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

    public static void setDataSource(String key) {
        HOLDER.set(key);
    }

    public static String getDataSource() {
        return HOLDER.get();
    }

    public static void clearDataSource() {
        HOLDER.remove();
    }
}
5. 创建动态数据源类

创建动态数据源类,继承AbstractRoutingDataSource

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;

public class DynamicDataSource extends AbstractRoutingDataSource {

    private static final Map<Object, Object> TARGET_DATA_SOURCES = new HashMap<>();

    static {
        // 将多个数据源添加到TARGET_DATA_SOURCES中
        TARGET_DATA_SOURCES.put("ds1", dataSource1());
        TARGET_DATA_SOURCES.put("ds2", dataSource2());
        TARGET_DATA_SOURCES.put("ds3", dataSource3());
    }

    public DynamicDataSource() {
        super.setDefaultTargetDataSource(dataSource1());
        super.setTargetDataSources(TARGET_DATA_SOURCES);
        super.afterPropertiesSet();
    }

    @Override

上一篇:五、函数封装及调用、参数及返回值、作用域、匿名函数、立即执行函数


下一篇:Android全局异常捕获