公司有个需求:通过数据库配置和前端请求,在数据库中执行一段脚本。这个需求的核心是配置动态数据源,而且需要在程序运行中配置多数据源。我这里用到了dynamic-datasource 的数据源扩展点实现此功能。
maven 坐标
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.22</version>
</dependency>
实现代码
//使用Spring Boot的扩展点,在容器启动成功后执行多数据源配置
@Configuration
public class DynamicDataSourceConfig implements ApplicationListener<ContextRefreshedEvent> {
//读取yml 文件里面主数据源名称,用于获取主数据源
@Value("${spring.datasource.dynamic.primary}")
private String dynamicPrimary;
//这个是我自己的数据源配置service
@Autowired
private IDbManageService dbManageService;
//核心动态数据源组件
@Autowired
private DynamicRoutingDataSource dynamicRoutingDataSource;
//Druid数据源创建器
@Autowired
private DruidDataSourceCreator dataSourceCreator;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
List<DbManage> dbManageList = dbManageService.list();
if (CollectionUtils.isEmpty(dbManageList)) {
return;
}
dbManageList.forEach(item -> {
//获取主数据源对象
DataSource masterDs = dynamicRoutingDataSource.getDataSource(dynamicPrimary);
DataSourceProperty dsProperty = new DataSourceProperty();
//copy 主数据源属性
BeanUtils.copyProperties(masterDs, dsProperty);
//修改数据库连接
dsProperty.setDriverClassName(item.getDriverClassName());
dsProperty.setUrl(item.getUrl());
dsProperty.setUsername(item.getUsername());
dsProperty.setPassword(item.getPassword());
//创建数据源
DataSource dataSource = dataSourceCreator.createDataSource(dsProperty);
//加入到数据源容器内
dynamicRoutingDataSource.addDataSource(item.getDsName(), dataSource);
});
}
}
yaml 配置(备用)
spring:
# 多数据源配置,需要移除默认的Druid 配置
autoconfigure:
exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
# 数据源配置
datasource:
type: com.alibaba.druid.pool.DruidDataSource
# 配置Druid监控
druid:
stat-view-servlet:
enabled: true
login-username: admin
login-password: 123456
dynamic:
# 配置Druid 的各项参数
druid:
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,wall用于防火墙
filters: stat
# 初始化大小、最小或最大
initial-size: 5
min-idle: 5
max-active: 20
# 获取连接等待超时的时间,单位毫秒
max-wait: 60000
# 配置间隔多久进行一次检测,检测需要关闭的空闲连接,单位是毫秒
time-between-eviction-runs-millis: 60000
# 配置一个连接在连接池中的最小生存时间,单位是毫秒
min-evictable-idle-time-millis: 300000
validation-query: SELECT 'x'
test-while-idle: true
test-on-borrow: false
test-on-return: false
# 打开PSCache,并且制定每个连接上PSCache的大小
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
stat:
merge-sql: true
log-slow-sql: true
slow-sql-millis: 3000
# 配置数据库参数
primary: master
strict: true
datasource:
master:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://192.168.110.232:3306/project_development_test?serverTimezone=GMT%2B8&characterEncoding=utf-8&autoReconnect=true&allowMultiQueries=true
username: projectDevelopment
password: projectDevelopment
poolPingQuery: SELECT NOW()
poolPingEnabled: true