项目需求背景
最近做项目的时候碰到一个需求还蛮不错的分享一下。
简化版:
根据输入的数据源信息(url,driverClassName,username,password)来连接新数据源,同时获取该数据源下所有的数据库名字。
这里采用的是dynamic动态数据库完成
直接上代码
<!-- 动态数据库 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.2.1</version>
</dependency>
dynamic-datasource-spring-boot-starter 是一个基于springboot的快速集成多数据源的启动器。
@Service
public class DbManagerServiceImpl implements DbManagerService {
@Resource
private DataSourceCreator dataSourceCreator;
@Override
public void test(DataSourceProperty dataSourceProperty) {
try {
DynamicUtil.getInstance().createNewDataSource(dataSourceProperty,dataSourceCreator);
List<String> list = commonSqlMapper.getAllDataBase();
list.forEach(s -> System.out.println(s));
return list;
} catch (Exception e) {
e.printStackTrace();
} finally {
DynamicDataSourceContextHolder.poll();
}
}
}
工具类:
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.creator.DataSourceCreator;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import javax.sql.DataSource;
public class DynamicUtil {
private static volatile DynamicRoutingDataSource instance2= null;
private static volatile DynamicUtil instance3 = null;
public DynamicUtil() {
}
public static synchronized DynamicUtil getInstance() {
//在getInstance方法上加同步
if (instance3 == null) {
instance3 = new DynamicUtil();
} else {
System.out.println("已经有一个数据源创建工具类,不能产生新的!");
}
return instance3;
}
public static synchronized DynamicRoutingDataSource getInstance2() {
//在getInstance方法上加同步
if (instance2 == null) {
instance2 = new DynamicRoutingDataSource();
} else {
System.out.println("已经有一个数据源管理器,不能产生新的!");
}
return instance2;
}
public void createNewDataSource(DataSourceProperty dataSourceProperty,DataSourceCreator dataSourceCreator)
{
DynamicRoutingDataSource drds2 = getInstance2();
System.out.println(dataSourceProperty);
//创建数据源并添加到系统中管理
DataSource dataSource = dataSourceCreator.createDataSource(dataSourceProperty);
String userName = dataSourceProperty.getUsername();
drds2.addDataSource(userName, dataSource);
DynamicDataSourceContextHolder.push(userName);
}
}
DataSourceProperty 是封装好的实体包含了用户名,url等信息
工具类采用单例模式,这里讲一下自己当时的误区
(要知道,DataSourceCreator是属于依赖,所以自动注入的时候不能放在另一个对象里,也就是不能放工具类里注入,因为自动注入实在编译期就分配好内存并放在spring容器中。)
工具类使用单例模式
push之后就可以使用新数据源了,然后业务逻辑完成后进行poll删除当前数据源
之后就会使用yml里的默认数据源
当然如果数据源确定好了也可以直接在yml里写死,通过注解切换。