zhaowenxuan
2025-02-07 1e3a838de89a277b2bc65761c0e5619a96a64813
20250207
3个文件已添加
114 ■■■■■ 已修改文件
ltkj-admin/src/main/java/com/ltkj/web/db/DataSourceConfig.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ltkj-admin/src/main/java/com/ltkj/web/db/DataSourceContextHolder.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ltkj-admin/src/main/java/com/ltkj/web/db/DynamicDataSource.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ltkj-admin/src/main/java/com/ltkj/web/db/DataSourceConfig.java
New file
@@ -0,0 +1,63 @@
package com.ltkj.web.db;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class DataSourceConfig {
    private static final String DEFAULT_DATA_SOURCE_KEY = "default"; // 主库的标识
    private final Map<String, DataSource> dataSourceCache = new HashMap<>(); // 数据源缓存
    // 从 application.yml 中读取主库的配置
    @Value("${spring.datasource.url}")
    private String primaryUrl;
    @Value("${spring.datasource.username}")
    private String primaryUsername;
    @Value("${spring.datasource.password}")
    private String primaryPassword;
    @Value("${dbUrl}")
    private String dbUrl;
    @Bean
    public DataSource dynamicDataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        // 初始化默认数据源为主库
        dynamicDataSource.addTargetDataSource(DEFAULT_DATA_SOURCE_KEY, createDataSource(primaryUrl, primaryUsername, primaryPassword));
        dynamicDataSource.setDefaultTargetDataSource(dynamicDataSource.getTargetDataSources().get(DEFAULT_DATA_SOURCE_KEY)); // 设置默认数据源
        return dynamicDataSource;
    }
    // 动态创建数据源
    private DataSource createDataSource(String url, String username, String password) {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(url);
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        return dataSource;
    }
    // 根据用户 ID 动态获取数据源
    public void addDataSource(String userId) {
        String dbName = "scum_admin_user_" + userId;
        // 检查缓存中是否已经存在该数据源
        if (!dataSourceCache.containsKey(userId)) {
            String url = "jdbc:mysql://"+dbUrl+":3306/"+dbName;
            DataSource dataSource = createDataSource(url, primaryUsername, primaryPassword);
            dataSourceCache.put(userId, dataSource);
            DynamicDataSource dynamicDataSource = (DynamicDataSource) dynamicDataSource();
            dynamicDataSource.addTargetDataSource(userId, dataSource);
        }
    }
}
ltkj-admin/src/main/java/com/ltkj/web/db/DataSourceContextHolder.java
New file
@@ -0,0 +1,17 @@
package com.ltkj.web.db;
public class DataSourceContextHolder {
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
    public static void setDataSourceKey(String key) {
        contextHolder.set(key);
    }
    public static String getDataSourceKey() {
        return contextHolder.get();
    }
    public static void clear() {
        contextHolder.remove();
    }
}
ltkj-admin/src/main/java/com/ltkj/web/db/DynamicDataSource.java
New file
@@ -0,0 +1,34 @@
package com.ltkj.web.db;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
public class DynamicDataSource extends AbstractRoutingDataSource {
    private final Map<Object, Object> targetDataSources = new HashMap<>(); // 存储所有数据源
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDataSourceKey(); // 根据上下文获取当前数据源的键
    }
    // 添加目标数据源
    public void addTargetDataSource(String key, DataSource dataSource) {
        targetDataSources.put(key, dataSource);
        super.setTargetDataSources(targetDataSources); // 更新目标数据源
        super.afterPropertiesSet(); // 重新初始化数据源
    }
    // 允许外部访问所有目标数据源
    @Override
    public void setTargetDataSources(Map<Object, Object> targetDataSources) {
        super.setTargetDataSources(targetDataSources);
    }
    public Map<Object, Object> getTargetDataSources() {
        return targetDataSources; // 获取所有目标数据源
    }
}