|
|
@@ -0,0 +1,149 @@
|
|
|
+package com.ruoyi.interfaces.database;
|
|
|
+
|
|
|
+import com.alibaba.druid.pool.DruidDataSource;
|
|
|
+import com.ruoyi.interfaces.domain.SysMetaDatasource;
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
+
|
|
|
+import javax.annotation.PreDestroy;
|
|
|
+import javax.sql.DataSource;
|
|
|
+import java.sql.SQLException;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.concurrent.ConcurrentHashMap;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 运行时数据源管理器
|
|
|
+ * 负责动态创建和管理Druid数据源
|
|
|
+ */
|
|
|
+@Component
|
|
|
+public class DynamicDataSourceManager {
|
|
|
+
|
|
|
+ // 使用线程安全的ConcurrentHashMap存储数据源
|
|
|
+ private final Map<String, DruidDataSource> dataSourceMap = new ConcurrentHashMap<>();
|
|
|
+
|
|
|
+ public HashMap<String,String> className = new HashMap<String,String>(){
|
|
|
+ {
|
|
|
+ put("mysql","com.mysql.cj.jdbc.Driver");
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ public DataSource getSysDataSource(SysMetaDatasource datasource){
|
|
|
+
|
|
|
+ String url = "jdbc:"+datasource.getDsType()+"://"+datasource.getDsIp()+":"+datasource.getDsPort()+"/"+datasource.getDsTitle();
|
|
|
+ return getOrCreateDataSource(url,
|
|
|
+ datasource.getDsUser(),
|
|
|
+ datasource.getDsPass(),
|
|
|
+ className.get(datasource.getDsType())
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建或获取数据源
|
|
|
+ * @param url 数据库连接URL
|
|
|
+ * @param username 用户名
|
|
|
+ * @param password 密码
|
|
|
+ * @param driverClassName 驱动类名
|
|
|
+ * @return 数据源实例
|
|
|
+ */
|
|
|
+ public DataSource getOrCreateDataSource(String url, String username, String password, String driverClassName) {
|
|
|
+ String dataSourceKey = generateKey(url, username);
|
|
|
+
|
|
|
+ // 如果已存在,直接返回
|
|
|
+ if (dataSourceMap.containsKey(dataSourceKey)) {
|
|
|
+ DruidDataSource existingDataSource = dataSourceMap.get(dataSourceKey);
|
|
|
+ if (!existingDataSource.isClosed()) {
|
|
|
+ return existingDataSource;
|
|
|
+ } else {
|
|
|
+ // 如果数据源已关闭,移除并重新创建
|
|
|
+ dataSourceMap.remove(dataSourceKey);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 创建新的数据源
|
|
|
+ DruidDataSource dataSource = createDataSource(url, username, password, driverClassName);
|
|
|
+ dataSourceMap.put(dataSourceKey, dataSource);
|
|
|
+
|
|
|
+ return dataSource;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建Druid数据源
|
|
|
+ */
|
|
|
+ private DruidDataSource createDataSource(String url, String username, String password, String driverClassName) {
|
|
|
+ DruidDataSource dataSource = new DruidDataSource();
|
|
|
+ dataSource.setUrl(url);
|
|
|
+ dataSource.setUsername(username);
|
|
|
+ dataSource.setPassword(password);
|
|
|
+ dataSource.setDriverClassName(driverClassName);
|
|
|
+
|
|
|
+ // 配置连接池参数
|
|
|
+ dataSource.setInitialSize(1);
|
|
|
+ dataSource.setMinIdle(3);
|
|
|
+ dataSource.setMaxActive(20);
|
|
|
+ dataSource.setMaxWait(60000);
|
|
|
+ dataSource.setTimeBetweenEvictionRunsMillis(60000);
|
|
|
+ dataSource.setMinEvictableIdleTimeMillis(300000);
|
|
|
+ dataSource.setTestWhileIdle(true);
|
|
|
+ dataSource.setTestOnBorrow(false);
|
|
|
+ dataSource.setTestOnReturn(false);
|
|
|
+ dataSource.setPoolPreparedStatements(true);
|
|
|
+ dataSource.setMaxPoolPreparedStatementPerConnectionSize(20);
|
|
|
+
|
|
|
+ try {
|
|
|
+ dataSource.setFilters("stat,wall");
|
|
|
+ dataSource.init(); // 显式初始化
|
|
|
+ } catch (SQLException e) {
|
|
|
+ throw new RuntimeException("初始化数据源失败: " + e.getMessage(), e);
|
|
|
+ }
|
|
|
+
|
|
|
+ return dataSource;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成数据源唯一键
|
|
|
+ */
|
|
|
+ private String generateKey(String url, String username) {
|
|
|
+ return url + "|" + username;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取所有已创建的数据源
|
|
|
+ */
|
|
|
+ public Map<String, DruidDataSource> getAllDataSources() {
|
|
|
+ return new ConcurrentHashMap<>(dataSourceMap);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 关闭指定数据源
|
|
|
+ */
|
|
|
+ public void closeDataSource(String url, String username) {
|
|
|
+ String key = generateKey(url, username);
|
|
|
+ DruidDataSource dataSource = dataSourceMap.get(key);
|
|
|
+ if (dataSource != null) {
|
|
|
+ dataSource.close();
|
|
|
+ dataSourceMap.remove(key);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 关闭所有数据源
|
|
|
+ */
|
|
|
+ @PreDestroy
|
|
|
+ public void closeAllDataSources() {
|
|
|
+ for (DruidDataSource dataSource : dataSourceMap.values()) {
|
|
|
+ if (!dataSource.isClosed()) {
|
|
|
+ dataSource.close();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ dataSourceMap.clear();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查数据源是否存在且有效
|
|
|
+ */
|
|
|
+ public boolean containsDataSource(String url, String username) {
|
|
|
+ String key = generateKey(url, username);
|
|
|
+ DruidDataSource dataSource = dataSourceMap.get(key);
|
|
|
+ return dataSource != null && !dataSource.isClosed();
|
|
|
+ }
|
|
|
+}
|