zhaowenxuan
2025-02-07 791b8c88d67767c9847c7c052faca3e65ec36016
配置动态切库类以及拦截器切库
5个文件已修改
1 文件已重命名
138 ■■■■ 已修改文件
ltkj-framework/src/main/java/com/ltkj/framework/config/WebConfig.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ltkj-framework/src/main/java/com/ltkj/framework/interceptor/DBChangeInterceptor.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ltkj-hosp/src/main/java/com/ltkj/db/DataSourceConfig.java 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ltkj-hosp/src/main/java/com/ltkj/db/HospDynamicDataSource.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ltkj-hosp/src/main/java/com/ltkj/hosp/domain/DictHosp.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ltkj-hosp/src/main/resources/mapper/hosp/DictHospMapper.xml 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ltkj-framework/src/main/java/com/ltkj/framework/config/WebConfig.java
@@ -1,5 +1,7 @@
package com.ltkj.framework.config;
import com.ltkj.framework.interceptor.DBChangeInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@@ -11,6 +13,10 @@
//定义拦截器
@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    private DBChangeInterceptor dbChangeInterceptor;
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new TokenInterceptor())
@@ -24,5 +30,8 @@
                        "/lis/**","/api/His/**","/pacs/**",
                        "/callBack/**"
                });
        registry.addInterceptor(dbChangeInterceptor)
                .addPathPatterns("/**");
    }
}
ltkj-framework/src/main/java/com/ltkj/framework/interceptor/DBChangeInterceptor.java
@@ -1,30 +1,64 @@
package com.ltkj.framework.interceptor;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.gson.Gson;
import com.ltkj.db.DataSourceConfig;
import com.ltkj.db.DataSourceContextHolder;
import com.ltkj.hosp.domain.DictHosp;
import com.ltkj.hosp.service.IDictHospService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
 * @Company: 西安路泰科技有限公司
 * @Author: zhaowenxuan
 * @Date: 2025/2/7 11:07
 */
@Component
@Order(2)
public class DBChangeInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
    @Autowired
    private IDictHospService dictHospService;
    @Autowired
    private DataSourceConfig dataSourceConfig;
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
        String hospId = request.getHeader("hospId");
        if (StrUtil.isBlank(hospId)){
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write("{\"message\":\"401:找不到院区编号\"}");
            return false;
        }
        DataSourceContextHolder.setDataSourceKey("default");
        LambdaQueryWrapper<DictHosp> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DictHosp::getCode,hospId);
        DictHosp hosp = dictHospService.getOne(wrapper);
        if (hosp == null || hosp.getDatabase() == null || hosp.getDatabase().trim().isEmpty()) {
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write("{\"message\":\"401:找不到院区数据\"}");
            return false;
        }
        dataSourceConfig.addDataSource(hosp.getDatabase());
        DataSourceContextHolder.setDataSourceKey(hosp.getDatabase());
        return true;
    }
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        DataSourceContextHolder.setDataSourceKey("default");
        DataSourceContextHolder.clear();
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}
ltkj-hosp/src/main/java/com/ltkj/db/DataSourceConfig.java
@@ -1,47 +1,49 @@
package com.ltkj.db;
import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Autowired;
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.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
//@Configuration
@Configuration
public class DataSourceConfig {
    // 使用代码
//    try {
//        long id = Long.parseLong(request.getAttribute("id").toString());
//        DataSourceContextHolder.setDataSourceKey(String.valueOf(id));
//        dataSourceConfig.addDataSource(String.valueOf(id)); // 确保数据源已注册
//        if (log.getSize()>50) log.setSize(50);
//        if (log.getLang().equals("zh-cn")) log.setLang("zh");
//        return serverLogService.getLog(log,id);
//    }finally {
//        DataSourceContextHolder.setDataSourceKey("default"); // 切换回主库
//    }
    private static final String DEFAULT_DATA_SOURCE_KEY = "default"; // 主库的标识
    private final Map<String, DataSource> dataSourceCache = new HashMap<>(); // 数据源缓存
    @Value("${config.properties}")
    private String url;
    @Value("${config.path}")
    private String path;
    // 从 application.yml 中读取主库的配置
    @Value("${spring.datasource.url}")
//    @Value("${spring.datasource.url}")
    private String primaryUrl;
    @Value("${spring.datasource.username}")
    private String primaryPort;
    //    @Value("${spring.datasource.username}")
    private String primaryUsername;
    @Value("${spring.datasource.password}")
    //    @Value("${spring.datasource.password}")
    private String primaryPassword;
    @Value("${dbUrl}")
    //    @Value("${dbUrl}")
    private String dbUrl;
    @Bean
    public DataSource dynamicDataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
    @Bean(name = "hospDynamicDataSources")
    public DataSource hospDynamicDataSources() {
        HospDynamicDataSource dynamicDataSource = new HospDynamicDataSource();
        // 初始化默认数据源为主库
        dynamicDataSource.addTargetDataSource(DEFAULT_DATA_SOURCE_KEY, createDataSource(primaryUrl, primaryUsername, primaryPassword));
@@ -60,15 +62,30 @@
    }
    // 根据用户 ID 动态获取数据源
    public void addDataSource(String userId) {
        String dbName = "scum_admin_user_" + userId;
    public void addDataSource(String dbName) {
        FileInputStream fis = null;
        Properties props = new Properties();
        try {
            fis = new FileInputStream(url);
            props.load(fis);
            fis.close();
            dbUrl = props.getProperty("ip");
            primaryPassword = props.getProperty("password");
            primaryPort = props.getProperty("prot");
            primaryUsername = props.getProperty("username");
        } catch (IOException e) {
            throw new RuntimeException("读取配置文件失败", e);
        }
        // 检查缓存中是否已经存在该数据源
        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);
        if (!dataSourceCache.containsKey(dbName)) {
            synchronized (this) {
                String url = "jdbc:mysql://" + dbUrl + ":" + primaryPort + "/" + dbName;
                DataSource dataSource = createDataSource(url, primaryUsername, primaryPassword);
                dataSourceCache.put(dbName, dataSource);
                HospDynamicDataSource dynamicDataSource = (HospDynamicDataSource) hospDynamicDataSources();
                dynamicDataSource.addTargetDataSource(dbName, dataSource);
            }
        }
    }
}
ltkj-hosp/src/main/java/com/ltkj/db/HospDynamicDataSource.java
File was renamed from ltkj-hosp/src/main/java/com/ltkj/db/DynamicDataSource.java
@@ -1,14 +1,17 @@
package com.ltkj.db;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class DynamicDataSource extends AbstractRoutingDataSource {
public class HospDynamicDataSource extends AbstractRoutingDataSource {
    private final Map<Object, Object> targetDataSources = new HashMap<>(); // 存储所有数据源
    private final Map<Object, Object> targetDataSources = new ConcurrentHashMap<>(); // 存储所有数据源
    @Override
    protected Object determineCurrentLookupKey() {
@@ -18,7 +21,7 @@
    // 添加目标数据源
    public void addTargetDataSource(String key, DataSource dataSource) {
        targetDataSources.put(key, dataSource);
        super.setTargetDataSources(targetDataSources); // 更新目标数据源
        super.setTargetDataSources(new ConcurrentHashMap<>(targetDataSources)); // 更新目标数据源
        super.afterPropertiesSet(); // 重新初始化数据源
    }
ltkj-hosp/src/main/java/com/ltkj/hosp/domain/DictHosp.java
@@ -206,6 +206,7 @@
                .append("updateByName", getUpdateByName())
                .append("imgbase64", getImgbase64())
                .append("deleted", getDeleted())
                .append("database", getDatabase())
                .toString();
    }
}
ltkj-hosp/src/main/resources/mapper/hosp/DictHospMapper.xml
@@ -31,6 +31,7 @@
        <result property="updateByName" column="update_by_name"/>
        <result property="imgbase64" column="imgBase64"/>
        <result property="deleted" column="deleted"/>
        <result property="database" column="database"/>
    </resultMap>
    <sql id="selectDictHospVo">
@@ -59,7 +60,7 @@
               create_by_name,
               update_by_name,
               imgBase64,
               deleted
               deleted,database
        from dict_hosp
    </sql>
@@ -116,6 +117,7 @@
            <if test="updateByName != null and updateByName != ''">update_by_name,</if>
            <if test="imgbase64 != null">imgBase64,</if>
            <if test="deleted != null">deleted,</if>
            <if test="database != null">database,</if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="hospAreaId != null">#{hospAreaId},</if>
@@ -144,6 +146,7 @@
            <if test="updateByName != null and updateByName != ''">#{updateByName},</if>
            <if test="imgbase64 != null">#{imgbase64},</if>
            <if test="deleted != null">#{deleted},</if>
            <if test="database != null">#{database},</if>
        </trim>
    </insert>
@@ -175,6 +178,7 @@
            <if test="updateByName != null and updateByName != ''">update_by_name = #{updateByName},</if>
            <if test="imgbase64 != null">imgBase64 = #{imgbase64},</if>
            <if test="deleted != null">deleted = #{deleted},</if>
            <if test="database != null">database = #{database},</if>
        </trim>
        where hosp_area_id = #{hospAreaId}
    </update>
@@ -191,4 +195,4 @@
            #{hospAreaId}
        </foreach>
    </delete>
</mapper>
</mapper>