动态数据源无需重启刷新

This commit is contained in:
1378012178@qq.com 2025-10-14 13:58:52 +08:00
parent 257db6a837
commit e9f729ebc8
3 changed files with 95 additions and 14 deletions

View File

@ -0,0 +1,24 @@
package com.nu.modules.common;
import org.jeecg.modules.data.loader.DataSourceLoader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 系统工具
*/
@RestController
@RequestMapping("/api/sysUtils")
public class SysUtilsApi {
@Autowired
private DataSourceLoader dataSourceLoader;
@PostMapping("/refreshDS")
public String refresh() {
dataSourceLoader.refreshDataSources();
return "数据源已刷新";
}
}

View File

@ -119,6 +119,7 @@ public class ShiroConfig {
filterChainDefinitionMap.put("/weixin/**", "anon"); //授权接口排除
filterChainDefinitionMap.put("/api/pad/loginApi/**", "anon"); //pad登录-信息获取接口
filterChainDefinitionMap.put("/sys/common/open/static/**", "anon");//获取本地文件资源
filterChainDefinitionMap.put("/api/sysUtils/refreshDS", "anon");//刷新数据源
filterChainDefinitionMap.put("/sys/getLoginQrcode/**", "anon"); //登录二维码
filterChainDefinitionMap.put("/sys/getQrcodeToken/**", "anon"); //监听扫码

View File

@ -12,6 +12,7 @@ import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import java.util.List;
import java.util.stream.Collectors;
@Slf4j
@Service
@ -27,11 +28,50 @@ public class DataSourceLoader {
refreshDataSources();
}
// public void refreshDataSources() {
// DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
// DataSource mainDataSource = ds.getDataSource("devops");
//
// // 从主数据源读取配置
// List<DataSourceEntity> configs = new JdbcTemplate(mainDataSource).query(
// "SELECT id, code, name, db_type, db_driver, db_url, db_name, db_username ,db_password ,sys_org_code FROM sys_data_source",
// (rs, rowNum) -> new DataSourceEntity(
// rs.getString("id"),
// rs.getString("code"),
// rs.getString("name"),
// rs.getString("db_type"),
// rs.getString("db_driver"),
// rs.getString("db_url"),
// rs.getString("db_name"),
// rs.getString("db_username"),
// rs.getString("db_password"),
// rs.getString("sys_org_code")
// )
// );
//
// // 创建并添加数据源
// configs.forEach(config -> {
// DataSourceProperty dataSourceProperty = new DataSourceProperty();
// dataSourceProperty.setUrl(config.getDbUrl());
// dataSourceProperty.setUsername(config.getDbUsername());
// String dbPassword = SecurityUtil.jiemi(config.getDbPassword());
// dataSourceProperty.setPassword(dbPassword);
// dataSourceProperty.setDriverClassName(config.getDbDriver());
// DataSource dynamicDataSource = dataSourceCreator.createDataSource(dataSourceProperty);
// ds.addDataSource(config.getCode(), dynamicDataSource);
// });
// }
public void refreshDataSources() {
DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
DataSource mainDataSource = ds.getDataSource("devops");
// 从主数据源读取配置
// 1. 从固定的主数据源 devops读取最新的动态数据源配置
DataSource mainDataSource = ds.getDataSource("devops"); // 必须是静态配置的不能被动态删除
if (mainDataSource == null) {
log.error("无法获取主数据源 'devops',刷新动态数据源失败!");
return;
}
List<DataSourceEntity> configs = new JdbcTemplate(mainDataSource).query(
"SELECT id, code, name, db_type, db_driver, db_url, db_name, db_username ,db_password ,sys_org_code FROM sys_data_source",
(rs, rowNum) -> new DataSourceEntity(
@ -48,17 +88,33 @@ public class DataSourceLoader {
)
);
// 创建并添加数据源
configs.forEach(config -> {
DataSourceProperty dataSourceProperty = new DataSourceProperty();
dataSourceProperty.setUrl(config.getDbUrl());
dataSourceProperty.setUsername(config.getDbUsername());
String dbPassword = SecurityUtil.jiemi(config.getDbPassword());
dataSourceProperty.setPassword(dbPassword);
dataSourceProperty.setDriverClassName(config.getDbDriver());
DataSource dynamicDataSource = dataSourceCreator.createDataSource(dataSourceProperty);
ds.addDataSource(config.getCode(), dynamicDataSource);
});
}
// 2. 新增或更新
for (DataSourceEntity config : configs) {
String code = config.getCode();
if (code == null || code.isEmpty()) {
log.warn("跳过无效数据源配置code 为空): {}", config);
continue;
}
try {
DataSourceProperty prop = new DataSourceProperty();
prop.setUrl(config.getDbUrl());
prop.setUsername(config.getDbUsername());
prop.setPassword(SecurityUtil.jiemi(config.getDbPassword()));
prop.setDriverClassName(config.getDbDriver());
DataSource newDs = dataSourceCreator.createDataSource(prop);
ds.addDataSource(code, newDs); // 如果已存在会先 close 旧的再替换DynamicRoutingDataSource 内部逻辑
log.info("已添加/更新动态数据源: {}", code);
} catch (Exception e) {
log.error("创建/更新数据源失败code={}", code, e);
}
}
log.info("动态数据源同步完成。当前动态数据源列表: {}",
ds.getDataSources().keySet().stream()
.filter(name -> !name.equals("master"))
.collect(Collectors.toList()));
}
}