java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > SpringBoot Druid与数据源切换

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

作者:码到三十五

微服务架构中多数据源切换是个常见的需求,Spring Boot 提供了强大的支持来简化这一过程.本文给大家介绍了SpringBoot中Druid连接池与多数据源切换的方法,需要的朋友可以参考下

多数据源切换原理

多数据源切换的原理主要基于 Spring 的 AbstractRoutingDataSource 类。AbstractRoutingDataSource 类允许根据运行时上下文动态选择数据源。其核心在于实现 determineCurrentLookupKey 方法,该方法决定当前操作使用哪个数据源。 AbstractRoutingDataSource 实现多数据源切换的原理:

1. 数据源映射

2. 数据源标识的确定

3. 数据源的选择与连接获取

4. 数据源切换的实现

实现步骤

1. 依赖

引入 MySQL 和 Druid 的依赖

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.6</version>
</dependency>

2. 配置数据源

在 application.yml 文件中配置多个数据源。

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      datasource1:
        url: jdbc:mysql://localhost:3306/master_db
        username: root
        password: password
        initial-size: 5
        min-idle: 5
        max-active: 20
        max-wait: 60000
      datasource2:
        url: jdbc:mysql://localhost:3306/slave_db
        username: root
        password: password
        initial-size: 5
        min-idle: 5
        max-active: 20
        max-wait: 60000

3. 创建数据源配置类

创建一个配置类来定义数据源 Bean。

@Configuration
public class DataSourceConfig {

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

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

    @Bean
    @Primary
    public DataSource dynamicDataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        dynamicDataSource.setDefaultTargetDataSource(dataSource1());
        Map<Object, Object> targetDataSources = new HashMap<>();
        targetDataSources.put("dataSource1", dataSource1());
        targetDataSources.put("dataSource2", dataSource2());
        dynamicDataSource.setTargetDataSources(targetDataSources);
        return dynamicDataSource;
    }
}

4. 实现 AbstractRoutingDataSource

创建一个继承自 AbstractRoutingDataSource 的类,并实现 determineCurrentLookupKey 方法。

public class DynamicDataSource extends AbstractRoutingDataSource {

    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDataSource();
    }
}

5. 创建 DataSourceContextHolder

创建一个工具类来保存当前线程的数据源信息。

public class DataSourceContextHolder {

    private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();

    public static void setDataSource(String dataSource) {
        CONTEXT_HOLDER.set(dataSource);
    }

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

    public static void clearDataSource() {
        CONTEXT_HOLDER.remove();
    }
}

6. AOP动态切换数据源

使用 AOP 在方法执行前后切换数据源。

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class DataSourceAspect {
	// 方法或者类上的横切点
    @Pointcut("@annotation(dataSource) || @within(dataSource)")
    public void dataSourcePointcut(DataSource dataSource) {}

    @Before("dataSourcePointcut(dataSource)")
    public void switchDataSource(JoinPoint joinPoint, DataSource dataSource) {
        // 从注解中获取数据源标识
        String dataSourceKey = dataSource.value();
        // 切换到指定的数据源
        DataSourceContextHolder.setDataSourceType(dataSourceKey);
    }

    @AfterReturning(pointcut = "dataSourcePointcut(dataSource)", returning = "result")
    public void restoreDataSource(JoinPoint joinPoint, DataSource dataSource, Object result) {
        // 恢复默认数据源(可选)
        DataSourceContextHolder.clearDataSourceType();
    }
}

/**
* 自定义注解
*/
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSource {

    String value() default "dataSource1";
}

7. 使用自定义注解

在需要切换数据源的方法上使用自定义注解。

注意

到此这篇关于SpringBoot中Druid连接池与多数据源切换的方法的文章就介绍到这了,更多相关SpringBoot Druid与数据源切换内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文