首先确定你的项目使用的动态数据源是spring-jdbc的还是苞米豆(baomidou)的dynamic-datasource-spring-boot-starter,苞米豆是对spring动态数据源的进一步封装,使用起来更容易,此次是针对使用苞米豆动态数据源依赖的使用。
动态加载外部数据源,意思是在容器启动的过程中,通过查询数据库表中配置的数据库连接要素,来动态的将该数据源加入到Bean中。而不是网上很多文章说的“Springboot如何使用动态数据眼,如何切换数据源”。
动态的加载外部数据源,比如说你要开发一个数据源管理模块,里面配置了四面八方的数据源信息,项目启动的时候或者项目运行的时候,可以把这些数据源都加载到项目中,而不是提前显示的配置到application.yml或者application.properties文件中。
=======================分割线=======================
定义数据源实体。
/**
*
*/
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;//当前连接状态
}
实现数据源实体的dao层service层以便实现增删改查。
定义监听类,监听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);
}
}
}
}
切换数据源
baomidou提供了@DS注解,怎么使用可以自己了解一下,也提供了DynamicDataSourceContextHolder操作类其静态方法push和poll就是压栈和弹出的操作,就完成一次数据源的切换。
//DynamicDataSourceContextHolder.push(genTable.getDataSourceName());
List<GenTableColumn> columnList = genDataBaseDictService.findTableColumnList(genTable);
//DynamicDataSourceContextHolder.poll();
检查连接
我们在加载完表中的数据源后还要增加一个检查连接的功能。