SpringBoot 配置多数据源

开始配置多数据源

首先我们需要先移除自动配置数据源,SpringBoot 的默认行为

DataSourceAutoConfiguration 是 SpringBoot 提供的自动配置类

java 复制代码
@SpringBootApplication(scanBasePackages = "com", exclude = {DataSourceAutoConfiguration.class})

下面首先读取了默认数据源的信息,通过 getProperties() 封装成一个 Map 对象

定义了一个名为 dynamicDataSource 的 bean 是数据源路由器,它继承了 AbstractRoutingDataSource 类,我们可以根据规则选择要使用的数据源。

dataSource 方法接受一个 Map,并返回一个数据源,于是我们就创建了一个数据源

这段代码通过设置,配置了一个支持动态切换的数据源,默认使用 master,用于运行时动态切换数据源。

java 复制代码
@Configuration
@Slf4j
public class DataSourceConfigurer {

    @Value("${spring.datasource.druid.master.url}")
    private String url;

    @Value("${spring.datasource.druid.master.username}")
    private String username;

    @Value("${spring.datasource.druid.master.password}")
    private String password;

    @Value("${spring.datasource.driverClassName}")
    private String driverClassName;

    /**
     * 获取数据源配置信息
     *
     * @return 数据源配置信息
     */
    private Map<String, Object> getProperties() {
        Map<String, Object> map = new HashMap<>();
        map.put("driverClassName", driverClassName);
        map.put("url", url);
        map.put("username", username);
        map.put("password", password);
        return map;
    }

    /**
     * 配置动态数据源
     *
     * @return 动态数据源
     */
    @Bean("dynamicDataSource")
    public DynamicRoutingDataSource dynamicDataSource() {
        DynamicRoutingDataSource dynamicRoutingDataSource = new DynamicRoutingDataSource();
        
        // 创建数据源
        DataSource dataSource = dynamicRoutingDataSource.dataSource(getProperties());
        
        // 设置数据源映射
        Map<Object, Object> dataSourceMap = new HashMap<>(1);
        dataSourceMap.put("default_db", dataSource);
        dynamicRoutingDataSource.setTargetDataSources(dataSourceMap);
        
        // 设置默认数据源
        dynamicRoutingDataSource.setDefaultTargetDataSource(dataSource);
        
        return dynamicRoutingDataSource;
    }
}

具体切换多数据源的逻辑 DynamicRoutingDataSource

多数据源切换的实现的关键是 AbstractRoutingDataSource

我们这里创建了一个 targetTargetDataSources 是一个 Map 存储数据源的数据,key 数据源的标识,value 是具体的数据源。通过 setTargetDataSources 可以设置数据源,在运行时,通过该方法切换。

通过 addDataSource 添加数据源,并通过 setTargetDataSources 使数据源生效。

existDataSource 是判断数据源是否存在

dataSource 这个是重要的方法,它是为数据源在druid 连接池中创建了资源,配置了数据源。

java 复制代码
/**
 * 动态数据源
 */
@Slf4j
public class DynamicRoutingDataSource extends AbstractRoutingDataSource {

    private static Map<Object, Object> targetTargetDataSources = new ConcurrentHashMap<>();

    @Override
    protected Object determineCurrentLookupKey() {
        // 每次连接数据库,都会去设置数据源
        return DynamicDataSourceContextHolder.getDataSourceKey();
    }

    // 设置targetDataSources并记录数据源(这里可以记录每个数据源的最近使用时间,可以做删除不经常使用的数据源)
    @Override
    public void setTargetDataSources(Map<Object, Object> targetDataSources) {
        super.setTargetDataSources(targetDataSources);
        super.afterPropertiesSet();
        targetTargetDataSources = targetDataSources;
    }

    // 添加数据源
    public void addDataSource(String tenant, Map<String, Object> dataSourceProperties) {
        targetTargetDataSources.put(tenant, dataSource(dataSourceProperties));
        super.setTargetDataSources(targetTargetDataSources);
        afterPropertiesSet();
    }

    // 判断是否存在数据源,存在直接取
    public boolean existDataSource(String tenant) {
        return targetTargetDataSources.containsKey(tenant);
    }

    // 组装数据源
    public DataSource dataSource(Map<String, Object> dataSourceProperties) {
        DataSource dataSource;
        try {
            dataSource = DruidDataSourceFactory.createDataSource(dataSourceProperties);
        } catch (Exception e) {
            log.error("dataSource: {}", e.getMessage());
            throw new RuntimeException();
        }
        return dataSource;
    }
}
相关推荐
2601_961901707 小时前
SpringBoot使用Nacos进行application.yml配置管理
java·spring boot·spring
Lost of 程序猿7 小时前
ASP.NET Core API 幂等性设计深度实战:从一次重复申领事故说起
后端·asp.net
何以解忧,唯有..8 小时前
LangChain 工具调用(Tool Calling)实战指南
java·前端·langchain
QQ_21696290968 小时前
【源码编号:project79475】SpringBoot校内二手交易平台:商品发布、分类检索、留言交流、订单管理全流程实战
java·spring boot·后端
软件聚导航9 小时前
「聚小软 AI 助手」技术升级:从数据库检索到 RAG 知识库问答
前端·数据库·mysql·微信小程序·小程序·ai编程·rag
学习星球9 小时前
单调栈——从“找下一个更大的“到柱状图中的最大矩形
数据库·c++·算法·leetcode·xcode
前端 贾公子9 小时前
第09章:上下文与记忆 (2)
java·服务器·前端
2601_962203519 小时前
Java进阶07集合(续)
java·开发语言
GoppViper10 小时前
RDF资源描述框架深度解析:语义Web的数据基石与实战逻辑
前端·数据库
郑州光合科技余经理10 小时前
本地生活服务系统:模块边界与结算字段怎么拆
java·开发语言·前端·后端·系统架构·uni-app·php