SpringBoot动态加载外部数据源

文章介绍了如何在SpringBoot项目中使用苞米豆动态数据源,动态加载数据库配置,避免硬编码。通过监听spring-context上下文刷新事件,在启动时从数据库获取数据源信息,创建DruidDataSource实例并添加到动态数据源中。同时提到了数据源实体、DAO层和服务层的实现,以及数据源的切换和连接检查功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先确定你的项目使用的动态数据源是spring-jdbc的还是苞米豆(baomidou)的dynamic-datasource-spring-boot-starter,苞米豆是对spring动态数据源的进一步封装,使用起来更容易,此次是针对使用苞米豆动态数据源依赖的使用。

动态加载外部数据源,意思是在容器启动的过程中,通过查询数据库表中配置的数据库连接要素,来动态的将该数据源加入到Bean中。而不是网上很多文章说的“Springboot如何使用动态数据眼,如何切换数据源”。

动态的加载外部数据源,比如说你要开发一个数据源管理模块,里面配置了四面八方的数据源信息,项目启动的时候或者项目运行的时候,可以把这些数据源都加载到项目中,而不是提前显示的配置到application.yml或者application.properties文件中。

=======================分割线=======================

  1. 定义数据源实体。

/**
 *
 */
package com.ims.system.datasource.entity;


import com.ims.core.entity.DataEntity;
import lombok.Data;

/**
 * sys_data_sourceEntity
 * @author admin
 * @version 2023-02-21
 */
@Data
public class SysDataSource extends DataEntity<SysDataSource> {

    private static final long serialVersionUID = 1L;
    private String key;        // 数据源别名
    private String name;        // 数据源名称
    private String descStr;        // 数据源描述
    private String dbType;        // 数据源类型
    private String driveClassName;        // 数据源驱动
    private String type;        // 数据源连接池
    private String userName;        // 用户
    private String passWord;        // 密码
    private String url;        // 连接url
    private String connStatus;//当前连接状态

}
  1. 实现数据源实体的dao层service层以便实现增删改查。

  1. 定义监听类,监听spring-context上下文刷新时间,在spring容器启动时加载数据源。

package com.ims.system.datasource.listener;

import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.ims.system.datasource.entity.SysDataSource;
import com.ims.system.datasource.service.ISysDataSourceService;
import com.ims.system.datasource.utils.SpringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

/**
 * 在spring容器启动时加载数据源:
 * 监听上下文刷新事件
 */
@Component
public class DataSourceInitListener implements ApplicationListener<ContextRefreshedEvent> {
    @Autowired
    private ISysDataSourceService sysDataSourceService;
    protected static final Logger LOGGER = LoggerFactory.getLogger(DataSourceInitListener.class);
    //重写事件方法
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        // 防止重复执行。
        if (event.getApplicationContext().getParent() == null || "bootstrap".equals(event.getApplicationContext().getParent().getId())) {
            loadDataSourceFromSysDataSource();
        }
    }
    /**
     * 加载系统数据源到dynamicDataSource中
     */
    private void loadDataSourceFromSysDataSource() {
        //这里的findAllList就是去库里查询所有配置在表中的数据源
        for (SysDataSource sysDataSource : sysDataSourceService.findAllList(new SysDataSource())) {
            try {
                //这里应该增加判断,如果是druid数据库连接池就是用DruidDataSource对象
                //如果是Hikari就是用HikariDataSource
                //这里数据库连接属性很多,我们目前只设置了四个基本要素,以后可以扩充其他
                DruidDataSource druidDataSource = new DruidDataSource();
                druidDataSource.setUrl(sysDataSource.getUrl());
                druidDataSource.setUsername(sysDataSource.getUserName());
                druidDataSource.setPassword(sysDataSource.getPassWord());
                druidDataSource.setDriverClassName(sysDataSource.getDriveClassName());
                //失败后是否中断,默认为false,会一直打印连不上一直重试
                druidDataSource.setBreakAfterAcquireFailure(true);
                //连接错误等待时间,默认为一分钟
                druidDataSource.setTimeBetweenConnectErrorMillis(6000);
                //快速失败
                druidDataSource.setFailFast(true);
                //其他两个属性不清楚,待查询
                druidDataSource.setTestOnBorrow(true);
                druidDataSource.setTestOnReturn(true);
                //将该配置增加到动态数据源中去,DynamicRoutingDataSource这个bean的name默认是dataSource,当然是用@Autowired也可以
                DynamicRoutingDataSource dataSource = (DynamicRoutingDataSource) SpringUtils.getBean("dataSource");
                dataSource.addDataSource(sysDataSource.getKey(), druidDataSource);
                LOGGER.debug("add datasource " + sysDataSource.getKey());
            } catch (Exception e) {
                LOGGER.error("在系统配置的数据源[" + sysDataSource.getKey() + "]启动项目时无法正确加载进去,请正确配置该数据源", e);
            }
        }
    }
}
  1. 切换数据源

baomidou提供了@DS注解,怎么使用可以自己了解一下,也提供了DynamicDataSourceContextHolder操作类其静态方法push和poll就是压栈和弹出的操作,就完成一次数据源的切换。

//DynamicDataSourceContextHolder.push(genTable.getDataSourceName());
List<GenTableColumn> columnList = genDataBaseDictService.findTableColumnList(genTable);
//DynamicDataSourceContextHolder.poll();
  1. 检查连接

我们在加载完表中的数据源后还要增加一个检查连接的功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dong__xue

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值