diff --git a/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-core/src/main/java/top/continew/starter/extension/tenant/autoconfigure/TenantProperties.java b/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-core/src/main/java/top/continew/starter/extension/tenant/autoconfigure/TenantProperties.java index cf0cad17..2f29145b 100644 --- a/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-core/src/main/java/top/continew/starter/extension/tenant/autoconfigure/TenantProperties.java +++ b/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-core/src/main/java/top/continew/starter/extension/tenant/autoconfigure/TenantProperties.java @@ -18,6 +18,7 @@ package top.continew.starter.extension.tenant.autoconfigure; import org.springframework.boot.context.properties.ConfigurationProperties; import top.continew.starter.core.constant.PropertiesConstants; +import top.continew.starter.extension.tenant.enums.TenantIsolationLevel; import java.util.List; @@ -35,6 +36,11 @@ public class TenantProperties { */ private boolean enabled = true; + /** + * 租户隔离级别 + */ + private TenantIsolationLevel isolationLevel = TenantIsolationLevel.LINE; + /** * 租户 ID 列名 */ @@ -63,6 +69,14 @@ public class TenantProperties { this.enabled = enabled; } + public TenantIsolationLevel getIsolationLevel() { + return isolationLevel; + } + + public void setIsolationLevel(TenantIsolationLevel isolationLevel) { + this.isolationLevel = isolationLevel; + } + public String getTenantIdColumn() { return tenantIdColumn; } diff --git a/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-core/src/main/java/top/continew/starter/extension/tenant/config/TenantProvider.java b/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-core/src/main/java/top/continew/starter/extension/tenant/config/TenantProvider.java index 9856fd1e..f6167f1a 100644 --- a/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-core/src/main/java/top/continew/starter/extension/tenant/config/TenantProvider.java +++ b/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-core/src/main/java/top/continew/starter/extension/tenant/config/TenantProvider.java @@ -19,7 +19,7 @@ package top.continew.starter.extension.tenant.config; import top.continew.starter.extension.tenant.context.TenantContext; /** - * 租户数据提供者 + * 租户提供者 * * @author Charles7c * @since 2.7.0 @@ -27,11 +27,11 @@ import top.continew.starter.extension.tenant.context.TenantContext; public interface TenantProvider { /** - * 根据租户ID获取租户数据 + * 根据租户 ID 获取租户上下文 * * @param tenantId 租户 ID - * @param verify 是否验证租户有效性 - * @return 数据源配置 + * @param isVerify 是否验证有效性 + * @return 租户上下文 */ - TenantContext getByTenantId(String tenantId, boolean verify); + TenantContext getByTenantId(String tenantId, boolean isVerify); } diff --git a/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-core/src/main/java/top/continew/starter/extension/tenant/context/TenantContextHolder.java b/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-core/src/main/java/top/continew/starter/extension/tenant/context/TenantContextHolder.java index c7261bde..9b272cce 100644 --- a/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-core/src/main/java/top/continew/starter/extension/tenant/context/TenantContextHolder.java +++ b/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-core/src/main/java/top/continew/starter/extension/tenant/context/TenantContextHolder.java @@ -16,7 +16,10 @@ package top.continew.starter.extension.tenant.context; +import cn.hutool.extra.spring.SpringUtil; import com.alibaba.ttl.TransmittableThreadLocal; +import top.continew.starter.extension.tenant.autoconfigure.TenantProperties; +import top.continew.starter.extension.tenant.config.TenantDataSource; import top.continew.starter.extension.tenant.enums.TenantIsolationLevel; import java.util.Optional; @@ -69,11 +72,22 @@ public class TenantContextHolder { } /** - * 获取隔离级别 + * 获取租户隔离级别 + * + * @return 租户隔离级别 */ public static TenantIsolationLevel getIsolationLevel() { return Optional.ofNullable(getContext()) .map(TenantContext::getIsolationLevel) - .orElse(TenantIsolationLevel.LINE); + .orElse(SpringUtil.getBean(TenantProperties.class).getIsolationLevel()); + } + + /** + * 获取租户数据源 + * + * @return 租户数据源 + */ + public static TenantDataSource getDataSource() { + return Optional.ofNullable(getContext()).map(TenantContext::getDataSource).orElse(null); } } diff --git a/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-core/src/main/java/top/continew/starter/extension/tenant/handler/TenantDataSourceHandler.java b/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-core/src/main/java/top/continew/starter/extension/tenant/handler/TenantDataSourceHandler.java index 1b5cb2ce..77779eff 100644 --- a/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-core/src/main/java/top/continew/starter/extension/tenant/handler/TenantDataSourceHandler.java +++ b/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-core/src/main/java/top/continew/starter/extension/tenant/handler/TenantDataSourceHandler.java @@ -31,6 +31,7 @@ public interface TenantDataSourceHandler { /** * 切换数据源 * + * @param tenantDataSource 数据源配置 */ void changeDataSource(TenantDataSource tenantDataSource); diff --git a/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-core/src/main/java/top/continew/starter/extension/tenant/handler/TenantHandler.java b/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-core/src/main/java/top/continew/starter/extension/tenant/handler/TenantHandler.java index d9a4f82b..db5da1fd 100644 --- a/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-core/src/main/java/top/continew/starter/extension/tenant/handler/TenantHandler.java +++ b/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-core/src/main/java/top/continew/starter/extension/tenant/handler/TenantHandler.java @@ -17,15 +17,18 @@ package top.continew.starter.extension.tenant.handler; /** - * @description: 租户处理器 - * @author: 小熊 - * @create: 2024-12-18 19:37 + * 租户处理器 + * + * @author 小熊 + * @since 2.8.0 */ public interface TenantHandler { /** - * 在指定租户中执行方法 + * 在指定租户中执行 + * + * @param tenantId 租户 ID + * @param runnable 方法 */ - void executeInTenant(Long tenantId, Runnable runnable); - + void execute(Long tenantId, Runnable runnable); } diff --git a/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/autoconfigure/TenantAutoConfiguration.java b/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/autoconfigure/TenantAutoConfiguration.java index 35015f2a..3b5e2cdd 100644 --- a/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/autoconfigure/TenantAutoConfiguration.java +++ b/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/autoconfigure/TenantAutoConfiguration.java @@ -20,6 +20,7 @@ import com.baomidou.dynamic.datasource.DynamicRoutingDataSource; import com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator; import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler; import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; +import jakarta.annotation.PostConstruct; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.NoSuchBeanDefinitionException; @@ -31,10 +32,16 @@ import org.springframework.context.annotation.Bean; import org.springframework.core.ResolvableType; import top.continew.starter.core.constant.PropertiesConstants; import top.continew.starter.extension.tenant.config.TenantProvider; -import top.continew.starter.extension.tenant.handler.*; +import top.continew.starter.extension.tenant.handler.DefaultTenantHandler; +import top.continew.starter.extension.tenant.handler.TenantDataSourceHandler; +import top.continew.starter.extension.tenant.handler.TenantHandler; +import top.continew.starter.extension.tenant.handler.datasource.DefaultTenantDataSourceHandler; +import top.continew.starter.extension.tenant.handler.datasource.TenantDataSourceAdvisor; +import top.continew.starter.extension.tenant.handler.datasource.TenantDataSourceInterceptor; +import top.continew.starter.extension.tenant.handler.line.DefaultTenantLineHandler; /** - * 多租户自动配置 + * 租户自动配置 * * @author Charles7c * @since 2.7.0 @@ -45,12 +52,10 @@ import top.continew.starter.extension.tenant.handler.*; public class TenantAutoConfiguration { private static final Logger log = LoggerFactory.getLogger(TenantAutoConfiguration.class); + private final TenantProperties tenantProperties; - private TenantAutoConfiguration() { - } - - static { - log.debug("[ContiNew Starter] - Auto Configuration 'Tenant' completed initialization."); + private TenantAutoConfiguration(TenantProperties tenantProperties) { + this.tenantProperties = tenantProperties; } /** @@ -100,11 +105,11 @@ public class TenantAutoConfiguration { } /** - * 多租户数据源提供者 + * 租户提供者 */ @Bean @ConditionalOnMissingBean - public TenantProvider tenantDataSourceProvider() { + public TenantProvider tenantProvider() { if (log.isErrorEnabled()) { log.error("Consider defining a bean of type '{}' in your configuration.", ResolvableType .forClass(TenantProvider.class)); @@ -118,7 +123,11 @@ public class TenantAutoConfiguration { @Bean @ConditionalOnMissingBean public TenantHandler tenantHandler(TenantDataSourceHandler tenantDataSourceHandler, TenantProvider tenantProvider) { - return new DefaultTenantHandler(tenantDataSourceHandler, tenantProvider); + return new DefaultTenantHandler(tenantProperties, tenantDataSourceHandler, tenantProvider); } + @PostConstruct + public void postConstruct() { + log.debug("[ContiNew Starter] - Auto Configuration 'Tenant' completed initialization."); + } } diff --git a/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/DefaultTenantHandler.java b/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/DefaultTenantHandler.java index 3be2de49..8819b20d 100644 --- a/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/DefaultTenantHandler.java +++ b/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/DefaultTenantHandler.java @@ -16,58 +16,62 @@ package top.continew.starter.extension.tenant.handler; -import cn.hutool.extra.spring.SpringUtil; import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder; +import top.continew.starter.extension.tenant.autoconfigure.TenantProperties; import top.continew.starter.extension.tenant.config.TenantProvider; import top.continew.starter.extension.tenant.context.TenantContext; import top.continew.starter.extension.tenant.context.TenantContextHolder; import top.continew.starter.extension.tenant.enums.TenantIsolationLevel; /** - * @description: 租户处理器 - * @author: 小熊 - * @create: 2024-12-18 19:43 + * 租户处理器 + * + * @author 小熊 + * @since 2.8.0 */ public class DefaultTenantHandler implements TenantHandler { + private final TenantProperties tenantProperties; private final TenantDataSourceHandler dataSourceHandler; private final TenantProvider tenantProvider; - public DefaultTenantHandler(TenantDataSourceHandler dataSourceHandler, TenantProvider tenantProvider) { + public DefaultTenantHandler(TenantProperties tenantProperties, + TenantDataSourceHandler dataSourceHandler, + TenantProvider tenantProvider) { + this.tenantProperties = tenantProperties; this.dataSourceHandler = dataSourceHandler; this.tenantProvider = tenantProvider; } @Override - public void executeInTenant(Long tenantId, Runnable runnable) { - boolean enabled = SpringUtil.getProperty("continew-starter.tenant.enabled", Boolean.class, false); - if (enabled) { - TenantContext tenantHandler = tenantProvider.getByTenantId(tenantId.toString(), false); - // 保存当前的租户上下文 - TenantContext originalContext = TenantContextHolder.getContext(); + public void execute(Long tenantId, Runnable runnable) { + if (!tenantProperties.isEnabled()) { + return; + } + TenantContext tenantHandler = tenantProvider.getByTenantId(tenantId.toString(), false); + // 保存当前的租户上下文 + TenantContext originalContext = TenantContextHolder.getContext(); + boolean isPush = false; + try { + // 设置新的租户上下文 + TenantContextHolder.setContext(tenantHandler); // 切换数据源 - boolean isPush = false; - try { - // 设置新的租户上下文 - TenantContextHolder.setContext(tenantHandler); - if (TenantIsolationLevel.DATASOURCE.equals(tenantHandler.getIsolationLevel())) { - //切换数据源 - dataSourceHandler.changeDataSource(tenantHandler.getDataSource()); - isPush = true; - } - runnable.run(); - } finally { - // 恢复原始的租户上下文 - if (originalContext != null) { - TenantContextHolder.setContext(originalContext); - } else { - TenantContextHolder.clearContext(); - } - if (isPush) { - DynamicDataSourceContextHolder.poll(); - } + if (TenantIsolationLevel.DATASOURCE.equals(tenantHandler.getIsolationLevel())) { + dataSourceHandler.changeDataSource(tenantHandler.getDataSource()); + isPush = true; + } + // 执行业务逻辑 + runnable.run(); + } finally { + // 恢复原始的租户上下文 + if (originalContext != null) { + TenantContextHolder.setContext(originalContext); + } else { + TenantContextHolder.clearContext(); + } + if (isPush) { + DynamicDataSourceContextHolder.poll(); } } } - } diff --git a/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/DefaultTenantDataSourceHandler.java b/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/datasource/DefaultTenantDataSourceHandler.java similarity index 81% rename from continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/DefaultTenantDataSourceHandler.java rename to continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/datasource/DefaultTenantDataSourceHandler.java index 0bbde05a..b628321b 100644 --- a/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/DefaultTenantDataSourceHandler.java +++ b/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/datasource/DefaultTenantDataSourceHandler.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package top.continew.starter.extension.tenant.handler; +package top.continew.starter.extension.tenant.handler.datasource; import cn.hutool.core.text.CharSequenceUtil; import com.baomidou.dynamic.datasource.DynamicRoutingDataSource; @@ -24,6 +24,7 @@ import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import top.continew.starter.extension.tenant.config.TenantDataSource; +import top.continew.starter.extension.tenant.handler.TenantDataSourceHandler; import javax.sql.DataSource; @@ -47,16 +48,17 @@ public class DefaultTenantDataSourceHandler implements TenantDataSourceHandler { @Override public void changeDataSource(TenantDataSource tenantDataSource) { - if (tenantDataSource != null) { - String dataSourceName = tenantDataSource.getPoolName(); - if (!this.containsDataSource(dataSourceName)) { - DataSource datasource = this.createDataSource(tenantDataSource); - dynamicRoutingDataSource.addDataSource(dataSourceName, datasource); - log.info("Load data source: {}", dataSourceName); - } - DynamicDataSourceContextHolder.push(dataSourceName); - log.info("Change data source: {}", dataSourceName); + if (tenantDataSource == null) { + return; } + String dataSourceName = tenantDataSource.getPoolName(); + if (!this.containsDataSource(dataSourceName)) { + DataSource datasource = this.createDataSource(tenantDataSource); + dynamicRoutingDataSource.addDataSource(dataSourceName, datasource); + log.info("Load data source: {}", dataSourceName); + } + DynamicDataSourceContextHolder.push(dataSourceName); + log.info("Change data source: {}", dataSourceName); } @Override diff --git a/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/TenantDataSourceAdvisor.java b/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/datasource/TenantDataSourceAdvisor.java similarity index 97% rename from continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/TenantDataSourceAdvisor.java rename to continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/datasource/TenantDataSourceAdvisor.java index 65f936cd..255407d3 100644 --- a/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/TenantDataSourceAdvisor.java +++ b/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/datasource/TenantDataSourceAdvisor.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package top.continew.starter.extension.tenant.handler; +package top.continew.starter.extension.tenant.handler.datasource; import org.aopalliance.aop.Advice; import org.springframework.aop.Pointcut; diff --git a/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/TenantDataSourceInterceptor.java b/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/datasource/TenantDataSourceInterceptor.java similarity index 70% rename from continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/TenantDataSourceInterceptor.java rename to continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/datasource/TenantDataSourceInterceptor.java index 1a39feef..607804e9 100644 --- a/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/TenantDataSourceInterceptor.java +++ b/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/datasource/TenantDataSourceInterceptor.java @@ -14,13 +14,14 @@ * limitations under the License. */ -package top.continew.starter.extension.tenant.handler; +package top.continew.starter.extension.tenant.handler.datasource; import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import top.continew.starter.extension.tenant.context.TenantContextHolder; import top.continew.starter.extension.tenant.enums.TenantIsolationLevel; +import top.continew.starter.extension.tenant.handler.TenantDataSourceHandler; /** * 租户数据源级隔离拦截器 @@ -38,20 +39,19 @@ public class TenantDataSourceInterceptor implements MethodInterceptor { @Override public Object invoke(MethodInvocation invocation) throws Throwable { - if (TenantContextHolder.getIsolationLevel() == TenantIsolationLevel.DATASOURCE) { - // 切换数据源 - boolean isPush = false; - try { - tenantDataSourceHandler.changeDataSource(TenantContextHolder.getContext().getDataSource()); - isPush = true; - return invocation.proceed(); - } finally { - if (isPush) { - DynamicDataSourceContextHolder.poll(); - } + if (TenantIsolationLevel.LINE.equals(TenantContextHolder.getIsolationLevel())) { + return invocation.proceed(); + } + // 切换数据源 + boolean isPush = false; + try { + tenantDataSourceHandler.changeDataSource(TenantContextHolder.getDataSource()); + isPush = true; + return invocation.proceed(); + } finally { + if (isPush) { + DynamicDataSourceContextHolder.poll(); } } - return invocation.proceed(); - } } diff --git a/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/DefaultTenantLineHandler.java b/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/line/DefaultTenantLineHandler.java similarity index 97% rename from continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/DefaultTenantLineHandler.java rename to continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/line/DefaultTenantLineHandler.java index 2f273b85..a12688d1 100644 --- a/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/DefaultTenantLineHandler.java +++ b/continew-starter-extension/continew-starter-extension-tenant/continew-starter-extension-tenant-mp/src/main/java/top/continew/starter/extension/tenant/handler/line/DefaultTenantLineHandler.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package top.continew.starter.extension.tenant.handler; +package top.continew.starter.extension.tenant.handler.line; import cn.hutool.core.collection.CollUtil; import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;