mirror of
https://github.com/continew-org/continew-starter.git
synced 2025-09-09 08:57:17 +08:00
feat(extension/tenant): 新增 TenantUtils 替换 TenantHandler 接口及其实现类 DefaultTenantHandler
This commit is contained in:
@@ -57,4 +57,9 @@ public interface TenantDataSourceHandler {
|
|||||||
* @param dataSourceName 数据源名称
|
* @param dataSourceName 数据源名称
|
||||||
*/
|
*/
|
||||||
void removeDataSource(String dataSourceName);
|
void removeDataSource(String dataSourceName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 轮询数据源
|
||||||
|
*/
|
||||||
|
void poll();
|
||||||
}
|
}
|
||||||
|
@@ -14,21 +14,22 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package top.continew.starter.extension.tenant;
|
package top.continew.starter.extension.tenant.annotation;
|
||||||
|
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import top.continew.starter.core.constant.PropertiesConstants;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 租户处理器
|
* 是否启用租户判断注解
|
||||||
*
|
*
|
||||||
* @author 小熊
|
* @author Charles7c
|
||||||
* @since 2.8.0
|
* @since 2.13.1
|
||||||
*/
|
*/
|
||||||
public interface TenantHandler {
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({ElementType.TYPE, ElementType.METHOD})
|
||||||
/**
|
@Documented
|
||||||
* 在指定租户中执行
|
@ConditionalOnProperty(prefix = PropertiesConstants.TENANT, name = PropertiesConstants.ENABLED, havingValue = "true", matchIfMissing = true)
|
||||||
*
|
public @interface ConditionalOnEnabledTenant {
|
||||||
* @param tenantId 租户 ID
|
}
|
||||||
* @param runnable 方法
|
|
||||||
*/
|
|
||||||
void execute(Long tenantId, Runnable runnable);
|
|
||||||
}
|
|
@@ -23,6 +23,7 @@ import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
|||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
import top.continew.starter.core.constant.PropertiesConstants;
|
import top.continew.starter.core.constant.PropertiesConstants;
|
||||||
import top.continew.starter.extension.tenant.config.TenantProvider;
|
import top.continew.starter.extension.tenant.config.TenantProvider;
|
||||||
|
import top.continew.starter.extension.tenant.interceptor.TenantInterceptor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 租户 Web MVC 自动配置
|
* 租户 Web MVC 自动配置
|
||||||
|
@@ -18,6 +18,7 @@ package top.continew.starter.extension.tenant.context;
|
|||||||
|
|
||||||
import cn.hutool.extra.spring.SpringUtil;
|
import cn.hutool.extra.spring.SpringUtil;
|
||||||
import com.alibaba.ttl.TransmittableThreadLocal;
|
import com.alibaba.ttl.TransmittableThreadLocal;
|
||||||
|
import top.continew.starter.core.util.SpringUtils;
|
||||||
import top.continew.starter.extension.tenant.autoconfigure.TenantProperties;
|
import top.continew.starter.extension.tenant.autoconfigure.TenantProperties;
|
||||||
import top.continew.starter.extension.tenant.config.TenantDataSource;
|
import top.continew.starter.extension.tenant.config.TenantDataSource;
|
||||||
import top.continew.starter.extension.tenant.enums.TenantIsolationLevel;
|
import top.continew.starter.extension.tenant.enums.TenantIsolationLevel;
|
||||||
@@ -35,12 +36,12 @@ public class TenantContextHolder {
|
|||||||
/**
|
/**
|
||||||
* 租户上下文
|
* 租户上下文
|
||||||
*/
|
*/
|
||||||
private static final TransmittableThreadLocal<TenantContext> CONTEXT = new TransmittableThreadLocal<>();
|
private static final TransmittableThreadLocal<TenantContext> CONTEXT_HOLDER = new TransmittableThreadLocal<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否忽略租户
|
* 是否忽略租户
|
||||||
*/
|
*/
|
||||||
private static final TransmittableThreadLocal<Boolean> IGNORE = new TransmittableThreadLocal<>();
|
private static final TransmittableThreadLocal<Boolean> IGNORE_HOLDER = new TransmittableThreadLocal<>();
|
||||||
|
|
||||||
private TenantContextHolder() {
|
private TenantContextHolder() {
|
||||||
}
|
}
|
||||||
@@ -51,7 +52,7 @@ public class TenantContextHolder {
|
|||||||
* @param context 上下文
|
* @param context 上下文
|
||||||
*/
|
*/
|
||||||
public static void setContext(TenantContext context) {
|
public static void setContext(TenantContext context) {
|
||||||
CONTEXT.set(context);
|
CONTEXT_HOLDER.set(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -60,7 +61,7 @@ public class TenantContextHolder {
|
|||||||
* @return 上下文
|
* @return 上下文
|
||||||
*/
|
*/
|
||||||
public static TenantContext getContext() {
|
public static TenantContext getContext() {
|
||||||
return CONTEXT.get();
|
return CONTEXT_HOLDER.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -69,7 +70,7 @@ public class TenantContextHolder {
|
|||||||
* @param ignore 是否忽略租户
|
* @param ignore 是否忽略租户
|
||||||
*/
|
*/
|
||||||
public static void setIgnore(boolean ignore) {
|
public static void setIgnore(boolean ignore) {
|
||||||
IGNORE.set(ignore);
|
IGNORE_HOLDER.set(ignore);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -78,15 +79,15 @@ public class TenantContextHolder {
|
|||||||
* @return 是否忽略租户
|
* @return 是否忽略租户
|
||||||
*/
|
*/
|
||||||
public static boolean isIgnore() {
|
public static boolean isIgnore() {
|
||||||
return Boolean.TRUE.equals(IGNORE.get());
|
return Boolean.TRUE.equals(IGNORE_HOLDER.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清除
|
* 清除
|
||||||
*/
|
*/
|
||||||
public static void clearContext() {
|
public static void clear() {
|
||||||
CONTEXT.remove();
|
CONTEXT_HOLDER.remove();
|
||||||
IGNORE.remove();
|
IGNORE_HOLDER.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -117,4 +118,23 @@ public class TenantContextHolder {
|
|||||||
public static TenantDataSource getDataSource() {
|
public static TenantDataSource getDataSource() {
|
||||||
return Optional.ofNullable(getContext()).map(TenantContext::getDataSource).orElse(null);
|
return Optional.ofNullable(getContext()).map(TenantContext::getDataSource).orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否启用了租户
|
||||||
|
*
|
||||||
|
* @return 是否启用了租户
|
||||||
|
*/
|
||||||
|
public static boolean isTenantEnabled() {
|
||||||
|
TenantProperties tenantProperties = SpringUtils.getBean(TenantProperties.class, true);
|
||||||
|
return tenantProperties != null && tenantProperties.isEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否禁用了租户
|
||||||
|
*
|
||||||
|
* @return 是否禁用了租户
|
||||||
|
*/
|
||||||
|
public static boolean isTenantDisabled() {
|
||||||
|
return !isTenantEnabled();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package top.continew.starter.extension.tenant.autoconfigure;
|
package top.continew.starter.extension.tenant.interceptor;
|
||||||
|
|
||||||
import cn.hutool.core.annotation.AnnotationUtil;
|
import cn.hutool.core.annotation.AnnotationUtil;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
@@ -23,6 +23,7 @@ import org.springframework.core.Ordered;
|
|||||||
import org.springframework.web.method.HandlerMethod;
|
import org.springframework.web.method.HandlerMethod;
|
||||||
import org.springframework.web.servlet.HandlerInterceptor;
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
import top.continew.starter.extension.tenant.annotation.TenantIgnore;
|
import top.continew.starter.extension.tenant.annotation.TenantIgnore;
|
||||||
|
import top.continew.starter.extension.tenant.autoconfigure.TenantProperties;
|
||||||
import top.continew.starter.extension.tenant.config.TenantProvider;
|
import top.continew.starter.extension.tenant.config.TenantProvider;
|
||||||
import top.continew.starter.extension.tenant.context.TenantContextHolder;
|
import top.continew.starter.extension.tenant.context.TenantContextHolder;
|
||||||
|
|
||||||
@@ -44,6 +45,7 @@ public class TenantInterceptor implements HandlerInterceptor, Ordered {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
|
||||||
|
// 忽略租户拦截
|
||||||
if (handler instanceof HandlerMethod handlerMethod) {
|
if (handler instanceof HandlerMethod handlerMethod) {
|
||||||
TenantIgnore methodAnnotation = handlerMethod.getMethodAnnotation(TenantIgnore.class);
|
TenantIgnore methodAnnotation = handlerMethod.getMethodAnnotation(TenantIgnore.class);
|
||||||
if (methodAnnotation != null) {
|
if (methodAnnotation != null) {
|
||||||
@@ -55,11 +57,18 @@ public class TenantInterceptor implements HandlerInterceptor, Ordered {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 设置上下文
|
||||||
String tenantId = request.getHeader(tenantProperties.getTenantIdHeader());
|
String tenantId = request.getHeader(tenantProperties.getTenantIdHeader());
|
||||||
TenantContextHolder.setContext(tenantProvider.getByTenantId(tenantId, true));
|
TenantContextHolder.setContext(tenantProvider.getByTenantId(tenantId, true));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) {
|
||||||
|
// 清除上下文
|
||||||
|
TenantContextHolder.clear();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getOrder() {
|
public int getOrder() {
|
||||||
return Integer.MIN_VALUE;
|
return Integer.MIN_VALUE;
|
@@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||||
|
* <p>
|
||||||
|
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* <p>
|
||||||
|
* http://www.gnu.org/licenses/lgpl.html
|
||||||
|
* <p>
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package top.continew.starter.extension.tenant.util;
|
||||||
|
|
||||||
|
import cn.hutool.extra.spring.SpringUtil;
|
||||||
|
import top.continew.starter.extension.tenant.TenantDataSourceHandler;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 租户工具类
|
||||||
|
*
|
||||||
|
* @author 小熊
|
||||||
|
* @author Charles7c
|
||||||
|
* @since 2.13.1
|
||||||
|
*/
|
||||||
|
public class TenantUtils {
|
||||||
|
|
||||||
|
private TenantUtils() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用指定租户执行业务逻辑
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 强制设置 {@code TenantContextHolder.setIgnore(false)},执行完恢复原值。<br>
|
||||||
|
* 适用于在非租户逻辑中执行有租户逻辑的业务逻辑。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param tenantId 租户 ID
|
||||||
|
* @param runnable 业务逻辑
|
||||||
|
*/
|
||||||
|
public static void execute(Long tenantId, Runnable runnable) {
|
||||||
|
// 未启用租户,直接执行业务逻辑
|
||||||
|
if (TenantContextHolder.isTenantDisabled()) {
|
||||||
|
runnable.run();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 原租户上下文
|
||||||
|
TenantContext oldContext = TenantContextHolder.getContext();
|
||||||
|
boolean oldIgnore = TenantContextHolder.isIgnore();
|
||||||
|
boolean isPush = false;
|
||||||
|
try {
|
||||||
|
TenantContext newContext = SpringUtil.getBean(TenantProvider.class)
|
||||||
|
.getByTenantId(tenantId.toString(), false);
|
||||||
|
// 设置新租户上下文
|
||||||
|
TenantContextHolder.setContext(newContext);
|
||||||
|
TenantContextHolder.setIgnore(false);
|
||||||
|
// 数据源级隔离:切换数据源
|
||||||
|
if (TenantIsolationLevel.DATASOURCE.equals(newContext.getIsolationLevel())) {
|
||||||
|
SpringUtil.getBean(TenantDataSourceHandler.class).changeDataSource(newContext.getDataSource());
|
||||||
|
isPush = true;
|
||||||
|
}
|
||||||
|
// 执行业务逻辑
|
||||||
|
runnable.run();
|
||||||
|
} finally {
|
||||||
|
// 恢复原租户上下文
|
||||||
|
TenantContextHolder.setContext(oldContext);
|
||||||
|
TenantContextHolder.setIgnore(oldIgnore);
|
||||||
|
if (isPush) {
|
||||||
|
SpringUtil.getBean(TenantDataSourceHandler.class).poll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 忽略租户执行业务逻辑
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 适用于在租户逻辑中执行非租户逻辑的业务逻辑。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param runnable 业务逻辑
|
||||||
|
*/
|
||||||
|
public void executeIgnore(Runnable runnable) {
|
||||||
|
// 未启用租户,直接执行业务逻辑
|
||||||
|
if (TenantContextHolder.isTenantDisabled()) {
|
||||||
|
runnable.run();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
boolean oldIgnore = TenantContextHolder.isIgnore();
|
||||||
|
try {
|
||||||
|
TenantContextHolder.setIgnore(true);
|
||||||
|
// 执行业务逻辑
|
||||||
|
runnable.run();
|
||||||
|
} finally {
|
||||||
|
TenantContextHolder.setIgnore(oldIgnore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -25,16 +25,13 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
|||||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|
||||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.core.ResolvableType;
|
import org.springframework.core.ResolvableType;
|
||||||
import top.continew.starter.core.constant.PropertiesConstants;
|
import top.continew.starter.extension.tenant.annotation.ConditionalOnEnabledTenant;
|
||||||
import top.continew.starter.extension.tenant.aop.TenantIgnoreAspect;
|
import top.continew.starter.extension.tenant.aop.TenantIgnoreAspect;
|
||||||
import top.continew.starter.extension.tenant.config.TenantProvider;
|
import top.continew.starter.extension.tenant.config.TenantProvider;
|
||||||
import top.continew.starter.extension.tenant.handler.DefaultTenantHandler;
|
|
||||||
import top.continew.starter.extension.tenant.TenantDataSourceHandler;
|
import top.continew.starter.extension.tenant.TenantDataSourceHandler;
|
||||||
import top.continew.starter.extension.tenant.TenantHandler;
|
|
||||||
import top.continew.starter.extension.tenant.handler.datasource.DefaultTenantDataSourceHandler;
|
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.TenantDataSourceAdvisor;
|
||||||
import top.continew.starter.extension.tenant.handler.datasource.TenantDataSourceInterceptor;
|
import top.continew.starter.extension.tenant.handler.datasource.TenantDataSourceInterceptor;
|
||||||
@@ -49,8 +46,8 @@ import javax.sql.DataSource;
|
|||||||
* @since 2.7.0
|
* @since 2.7.0
|
||||||
*/
|
*/
|
||||||
@AutoConfiguration
|
@AutoConfiguration
|
||||||
|
@ConditionalOnEnabledTenant
|
||||||
@EnableConfigurationProperties(TenantProperties.class)
|
@EnableConfigurationProperties(TenantProperties.class)
|
||||||
@ConditionalOnProperty(prefix = PropertiesConstants.TENANT, name = PropertiesConstants.ENABLED, havingValue = "true", matchIfMissing = true)
|
|
||||||
public class TenantAutoConfiguration {
|
public class TenantAutoConfiguration {
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(TenantAutoConfiguration.class);
|
private static final Logger log = LoggerFactory.getLogger(TenantAutoConfiguration.class);
|
||||||
@@ -130,15 +127,6 @@ public class TenantAutoConfiguration {
|
|||||||
throw new NoSuchBeanDefinitionException(TenantProvider.class);
|
throw new NoSuchBeanDefinitionException(TenantProvider.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 租户处理器
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
@ConditionalOnMissingBean
|
|
||||||
public TenantHandler tenantHandler(TenantProvider tenantProvider) {
|
|
||||||
return new DefaultTenantHandler(tenantProperties, tenantProvider);
|
|
||||||
}
|
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void postConstruct() {
|
public void postConstruct() {
|
||||||
log.debug("[ContiNew Starter] - Auto Configuration 'Tenant' completed initialization.");
|
log.debug("[ContiNew Starter] - Auto Configuration 'Tenant' completed initialization.");
|
||||||
|
@@ -1,76 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
|
||||||
* <p>
|
|
||||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
* <p>
|
|
||||||
* http://www.gnu.org/licenses/lgpl.html
|
|
||||||
* <p>
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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.TenantDataSourceHandler;
|
|
||||||
import top.continew.starter.extension.tenant.TenantHandler;
|
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 租户处理器
|
|
||||||
*
|
|
||||||
* @author 小熊
|
|
||||||
* @since 2.8.0
|
|
||||||
*/
|
|
||||||
public class DefaultTenantHandler implements TenantHandler {
|
|
||||||
|
|
||||||
private final TenantProperties tenantProperties;
|
|
||||||
private final TenantProvider tenantProvider;
|
|
||||||
|
|
||||||
public DefaultTenantHandler(TenantProperties tenantProperties, TenantProvider tenantProvider) {
|
|
||||||
this.tenantProperties = tenantProperties;
|
|
||||||
this.tenantProvider = tenantProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(Long tenantId, Runnable runnable) {
|
|
||||||
if (!tenantProperties.isEnabled()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
TenantContext tenantContext = tenantProvider.getByTenantId(tenantId.toString(), false);
|
|
||||||
// 保存当前的租户上下文
|
|
||||||
TenantContext originalContext = TenantContextHolder.getContext();
|
|
||||||
boolean isPush = false;
|
|
||||||
try {
|
|
||||||
// 设置新的租户上下文
|
|
||||||
TenantContextHolder.setContext(tenantContext);
|
|
||||||
// 切换数据源
|
|
||||||
if (TenantIsolationLevel.DATASOURCE.equals(tenantContext.getIsolationLevel())) {
|
|
||||||
SpringUtil.getBean(TenantDataSourceHandler.class).changeDataSource(tenantContext.getDataSource());
|
|
||||||
isPush = true;
|
|
||||||
}
|
|
||||||
// 执行业务逻辑
|
|
||||||
runnable.run();
|
|
||||||
} finally {
|
|
||||||
// 恢复原始的租户上下文
|
|
||||||
if (originalContext != null) {
|
|
||||||
TenantContextHolder.setContext(originalContext);
|
|
||||||
} else {
|
|
||||||
TenantContextHolder.clearContext();
|
|
||||||
}
|
|
||||||
if (isPush) {
|
|
||||||
DynamicDataSourceContextHolder.poll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -82,4 +82,9 @@ public class DefaultTenantDataSourceHandler implements TenantDataSourceHandler {
|
|||||||
public void removeDataSource(String dataSourceName) {
|
public void removeDataSource(String dataSourceName) {
|
||||||
dynamicRoutingDataSource.removeDataSource(dataSourceName);
|
dynamicRoutingDataSource.removeDataSource(dataSourceName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void poll() {
|
||||||
|
DynamicDataSourceContextHolder.poll();
|
||||||
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user