|
|
@@ -1,7 +1,12 @@
|
|
|
package com.fs.framework.datasource;
|
|
|
|
|
|
import com.alibaba.druid.pool.DruidDataSource;
|
|
|
+import com.fs.common.enums.DataSourceType;
|
|
|
+import com.fs.framework.datasource.DynamicDataSourceContextHolder;
|
|
|
import com.fs.tenant.domain.TenantInfo;
|
|
|
+import com.fs.tenant.service.TenantInfoService;
|
|
|
+import org.slf4j.Logger;
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.stereotype.Component;
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
@@ -13,9 +18,14 @@ import java.util.concurrent.ConcurrentHashMap;
|
|
|
@Component
|
|
|
public class TenantDataSourceManager {
|
|
|
|
|
|
+ private static final Logger log = LoggerFactory.getLogger(TenantDataSourceManager.class);
|
|
|
+
|
|
|
@Resource
|
|
|
private DynamicDataSource dynamicDataSource;
|
|
|
|
|
|
+ @Resource
|
|
|
+ private TenantInfoService tenantInfoService;
|
|
|
+
|
|
|
/**
|
|
|
* 租户数据源缓存
|
|
|
*/
|
|
|
@@ -60,6 +70,46 @@ public class TenantDataSourceManager {
|
|
|
DynamicDataSourceContextHolder.clearDataSourceType();
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 根据租户ID确保数据源已注册并切换(用于 Filter/拦截器等非登录场景)
|
|
|
+ * 解决 JVM 重启后 TENANT_DS_CACHE 被清空,导致 resolvedDataSources 中找不到租户数据源的问题
|
|
|
+ *
|
|
|
+ * @param tenantId 租户ID
|
|
|
+ */
|
|
|
+ public void ensureSwitchByTenantId(Long tenantId) {
|
|
|
+ String tenantKey = buildTenantKey(tenantId);
|
|
|
+
|
|
|
+ // 如果缓存中已有,直接切库
|
|
|
+ if (TENANT_DS_CACHE.containsKey(tenantKey)) {
|
|
|
+ DynamicDataSourceContextHolder.setDataSourceType(tenantKey);
|
|
|
+ log.debug("[TenantDS] 数据源已缓存,直接切换: {}", tenantKey);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 缓存中没有,需要从主库查租户信息并注册数据源
|
|
|
+ // 先临时切到主库
|
|
|
+ DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
|
|
|
+ try {
|
|
|
+ TenantInfo tenantInfo = tenantInfoService.getById(tenantId);
|
|
|
+ if (tenantInfo == null) {
|
|
|
+ log.warn("[TenantDS] 租户ID={} 在主库中不存在,回退到主库", tenantId);
|
|
|
+ DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (!tenantInfo.getStatus().equals(1)) {
|
|
|
+ log.warn("[TenantDS] 租户ID={} 已禁用,回退到主库", tenantId);
|
|
|
+ DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 注册并切换
|
|
|
+ switchTenant(tenantInfo);
|
|
|
+ log.info("[TenantDS] 动态注册并切换数据源: key={}, url={}", tenantKey, tenantInfo.getDbUrl());
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("[TenantDS] 动态注册租户数据源失败, tenantId={}, 回退到主库", tenantId, e);
|
|
|
+ DynamicDataSourceContextHolder.setDataSourceType(DataSourceType.MASTER.name());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 创建租户数据源(MySQL + Druid)
|
|
|
*/
|