diff --git a/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/config/TenantConfig.java b/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/config/TenantConfig.java new file mode 100644 index 0000000..4344f36 --- /dev/null +++ b/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/config/TenantConfig.java @@ -0,0 +1,84 @@ +package com.ruoyi.common.tenant.config; + +import cn.dev33.satoken.dao.SaTokenDao; +import cn.hutool.core.util.ObjectUtil; +import com.mybatisflex.core.tenant.TenantFactory; +import com.ruoyi.common.core.utils.reflect.ReflectUtils; +import com.ruoyi.common.orm.config.MyBatisFlexConfig; +import com.ruoyi.common.redis.config.RedisConfig; +import com.ruoyi.common.redis.config.properties.RedissonProperties; +import com.ruoyi.common.tenant.core.TenantSaTokenDao; +import com.ruoyi.common.tenant.handle.MyTenantFactory; +import com.ruoyi.common.tenant.handle.TenantKeyPrefixHandler; +import com.ruoyi.common.tenant.manager.TenantSpringCacheManager; +import com.ruoyi.common.tenant.properties.TenantProperties; +import org.redisson.config.ClusterServersConfig; +import org.redisson.config.SingleServerConfig; +import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer; +import org.springframework.boot.autoconfigure.AutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.cache.CacheManager; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; + +/** + * 租户配置类 + * + * @author Lion Li + * @author 数据小王子 + */ +@EnableConfigurationProperties(TenantProperties.class) +@AutoConfiguration(after = {RedisConfig.class, MyBatisFlexConfig.class}) +@ConditionalOnProperty(value = "tenant.enable", havingValue = "true") +public class TenantConfig { + + + /** + * 多租户工厂,用于获取当前租户ID + */ + @Bean + public TenantFactory tenantFactory() { + return new MyTenantFactory(); + } + + @Bean + public RedissonAutoConfigurationCustomizer tenantRedissonCustomizer(RedissonProperties redissonProperties) { + return config -> { + TenantKeyPrefixHandler nameMapper = new TenantKeyPrefixHandler(redissonProperties.getKeyPrefix()); + SingleServerConfig singleServerConfig = ReflectUtils.invokeGetter(config, "singleServerConfig"); + if (ObjectUtil.isNotNull(singleServerConfig)) { + // 使用单机模式 + // 设置多租户 redis key前缀 + singleServerConfig.setNameMapper(nameMapper); + ReflectUtils.invokeSetter(config, "singleServerConfig", singleServerConfig); + } + ClusterServersConfig clusterServersConfig = ReflectUtils.invokeGetter(config, "clusterServersConfig"); + // 集群配置方式 参考下方注释 + if (ObjectUtil.isNotNull(clusterServersConfig)) { + // 设置多租户 redis key前缀 + clusterServersConfig.setNameMapper(nameMapper); + ReflectUtils.invokeSetter(config, "clusterServersConfig", clusterServersConfig); + } + }; + } + + /** + * 多租户缓存管理器 + */ + @Primary + @Bean + public CacheManager tenantCacheManager() { + return new TenantSpringCacheManager(); + } + + /** + * 多租户鉴权dao实现 + */ + @Primary + @Bean + public SaTokenDao tenantSaTokenDao() { + return new TenantSaTokenDao(); + } + +} diff --git a/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/core/TenantEntity.java b/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/core/TenantEntity.java deleted file mode 100644 index cdd40e6..0000000 --- a/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/core/TenantEntity.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.ruoyi.common.tenant.core; - -import com.ruoyi.common.core.validate.EditGroup; -import com.ruoyi.common.orm.core.domain.BaseEntity; -import jakarta.validation.constraints.NotNull; -import lombok.Data; -import lombok.EqualsAndHashCode; - -/** - * 租户基类 - * - * @author Michelle.Chung - */ -@Data -@EqualsAndHashCode(callSuper = true) -public class TenantEntity extends BaseEntity { - - /** - * 租户编号 - */ - private Long tenantId; - -} diff --git a/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/handle/MyTenantFactory.java b/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/handle/MyTenantFactory.java new file mode 100644 index 0000000..bcfe59e --- /dev/null +++ b/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/handle/MyTenantFactory.java @@ -0,0 +1,32 @@ +package com.ruoyi.common.tenant.handle; + +import cn.hutool.core.util.ObjectUtil; +import com.mybatisflex.core.tenant.TenantFactory; +import com.ruoyi.common.security.utils.LoginHelper; +import com.ruoyi.common.tenant.helper.TenantHelper; +import lombok.AllArgsConstructor; + +/** + * 自定义租户处理器 + * + * @author 数据小王子 + */ +@AllArgsConstructor +public class MyTenantFactory implements TenantFactory { + + @Override + public Object[] getTenantIds() { + Long tenantId = LoginHelper.getTenantId(); + if (ObjectUtil.isNull(tenantId)) { + return null; + } + Long dynamicTenantId = TenantHelper.getDynamic(); + if (ObjectUtil.isNotNull(dynamicTenantId)) { + // 返回动态租户 + return new Object[]{dynamicTenantId}; + } + // 返回固定租户 + return new Object[]{tenantId}; + } + +} diff --git a/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/handle/PlusTenantLineHandler.java b/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/handle/PlusTenantLineHandler.java deleted file mode 100644 index 8b12552..0000000 --- a/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/handle/PlusTenantLineHandler.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.ruoyi.common.tenant.handle; - -import cn.hutool.core.collection.ListUtil; -import com.ruoyi.common.core.utils.StringUtils; -import com.ruoyi.common.security.utils.LoginHelper; -import com.ruoyi.common.tenant.helper.TenantHelper; -import com.ruoyi.common.tenant.properties.TenantProperties; -import lombok.AllArgsConstructor; -import net.sf.jsqlparser.expression.Expression; -import net.sf.jsqlparser.expression.NullValue; -import net.sf.jsqlparser.expression.StringValue; - -import java.util.List; - -/** - * 自定义租户处理器 - * - * @author Lion Li - */ -@AllArgsConstructor -//public class PlusTenantLineHandler implements TenantLineHandler { -public class PlusTenantLineHandler { - - private final TenantProperties tenantProperties; - - public Expression getTenantId() { - String tenantId = LoginHelper.getTenantId().toString(); - if (StringUtils.isBlank(tenantId)) { - return new NullValue(); - } - String dynamicTenantId = TenantHelper.getDynamic(); - if (StringUtils.isNotBlank(dynamicTenantId)) { - // 返回动态租户 - return new StringValue(dynamicTenantId); - } - // 返回固定租户 - return new StringValue(tenantId); - } - - public boolean ignoreTable(String tableName) { - String tenantId = LoginHelper.getTenantId().toString(); - // 判断是否有租户 - if (StringUtils.isNotBlank(tenantId)) { - // 不需要过滤租户的表 - List excludes = tenantProperties.getExcludes(); - // 非业务表 - List tables = ListUtil.toList( - "gen_table", - "gen_table_column" - ); - tables.addAll(excludes); - return tables.contains(tableName); - } - return true; - } - -} diff --git a/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/handle/TenantKeyPrefixHandler.java b/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/handle/TenantKeyPrefixHandler.java index 729702d..5980483 100644 --- a/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/handle/TenantKeyPrefixHandler.java +++ b/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/handle/TenantKeyPrefixHandler.java @@ -1,15 +1,19 @@ package com.ruoyi.common.tenant.handle; +import cn.hutool.core.util.ObjectUtil; import com.ruoyi.common.core.constant.GlobalConstants; import com.ruoyi.common.core.utils.StringUtils; import com.ruoyi.common.redis.handler.KeyPrefixHandler; import com.ruoyi.common.tenant.helper.TenantHelper; +import lombok.extern.slf4j.Slf4j; /** * 多租户redis缓存key前缀处理 * * @author Lion Li + * @author 数据小王子 */ +@Slf4j public class TenantKeyPrefixHandler extends KeyPrefixHandler { public TenantKeyPrefixHandler(String keyPrefix) { @@ -27,8 +31,11 @@ public class TenantKeyPrefixHandler extends KeyPrefixHandler { if (StringUtils.contains(name, GlobalConstants.GLOBAL_REDIS_KEY)) { return super.map(name); } - String tenantId = TenantHelper.getTenantId(); - if (StringUtils.startsWith(name, tenantId)) { + Long tenantId = TenantHelper.getTenantId(); + if (ObjectUtil.isNull(tenantId)) { + log.error("无法获取有效的租户id -> Null"); + } + if (StringUtils.startsWith(name, tenantId + "")) { // 如果存在则直接返回 return super.map(name); } @@ -47,8 +54,8 @@ public class TenantKeyPrefixHandler extends KeyPrefixHandler { if (StringUtils.contains(name, GlobalConstants.GLOBAL_REDIS_KEY)) { return super.unmap(name); } - String tenantId = TenantHelper.getTenantId(); - if (StringUtils.startsWith(unmap, tenantId)) { + Long tenantId = TenantHelper.getTenantId(); + if (StringUtils.startsWith(unmap, tenantId + "")) { // 如果存在则删除 return unmap.substring((tenantId + ":").length()); } diff --git a/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/helper/TenantHelper.java b/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/helper/TenantHelper.java index 8c0ff5c..8e37328 100644 --- a/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/helper/TenantHelper.java +++ b/ruoyi-common/ruoyi-common-tenant/src/main/java/com/ruoyi/common/tenant/helper/TenantHelper.java @@ -3,7 +3,9 @@ package com.ruoyi.common.tenant.helper; import cn.dev33.satoken.context.SaHolder; import cn.dev33.satoken.spring.SpringMVCUtil; import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.ObjectUtil; import com.alibaba.ttl.TransmittableThreadLocal; +import com.mybatisflex.core.tenant.TenantManager; import lombok.AccessLevel; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -19,6 +21,7 @@ import java.util.function.Supplier; * 租户助手 * * @author Lion Li + * @author 数据小王子 */ @Slf4j @NoArgsConstructor(access = AccessLevel.PRIVATE) @@ -26,7 +29,7 @@ public class TenantHelper { private static final String DYNAMIC_TENANT_KEY = GlobalConstants.GLOBAL_REDIS_KEY + "dynamicTenant"; - private static final ThreadLocal TEMP_DYNAMIC_TENANT = new TransmittableThreadLocal<>(); + private static final ThreadLocal TEMP_DYNAMIC_TENANT = new TransmittableThreadLocal<>(); /** * 租户功能是否启用 @@ -39,14 +42,14 @@ public class TenantHelper { * 开启忽略租户(开启后需手动调用 {@link #disableIgnore()} 关闭) */ public static void enableIgnore() { - //InterceptorIgnoreHelper.handle(IgnoreStrategy.builder().tenantLine(true).build()); + TenantManager.ignoreTenantCondition(); } /** * 关闭忽略租户 */ public static void disableIgnore() { - //InterceptorIgnoreHelper.clearIgnoreStrategy(); + TenantManager.restoreTenantCondition(); } /** @@ -82,7 +85,7 @@ public class TenantHelper { *

* 如果为非web环境 那么只在当前线程内生效 */ - public static void setDynamic(String tenantId) { + public static void setDynamic(Long tenantId) { if (!SpringMVCUtil.isWeb()) { TEMP_DYNAMIC_TENANT.set(tenantId); return; @@ -97,13 +100,13 @@ public class TenantHelper { *

* 如果为非web环境 那么只在当前线程内生效 */ - public static String getDynamic() { + public static Long getDynamic() { if (!SpringMVCUtil.isWeb()) { return TEMP_DYNAMIC_TENANT.get(); } String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId(); - String tenantId = (String) SaHolder.getStorage().get(cacheKey); - if (StringUtils.isNotBlank(tenantId)) { + Long tenantId = (Long) SaHolder.getStorage().get(cacheKey); + if (ObjectUtil.isNotNull(tenantId)) { return tenantId; } tenantId = RedisUtils.getCacheObject(cacheKey); @@ -124,13 +127,44 @@ public class TenantHelper { SaHolder.getStorage().delete(cacheKey); } + /** + * 在动态租户中执行 + * + * @param handle 处理执行方法 + */ + public static void dynamic(Long tenantId, Runnable handle) { + setDynamic(tenantId); + try { + handle.run(); + } finally { + clearDynamic(); + } + } + + /** + * 在动态租户中执行 + * + * @param handle 处理执行方法 + */ + public static T dynamic(Long tenantId, Supplier handle) { + setDynamic(tenantId); + try { + return handle.get(); + } finally { + clearDynamic(); + } + } + /** * 获取当前租户id(动态租户优先) */ - public static String getTenantId() { - String tenantId = TenantHelper.getDynamic(); - if (StringUtils.isBlank(tenantId)) { - tenantId = LoginHelper.getTenantId().toString(); + public static Long getTenantId() { + if (!isEnable()) { + return null; + } + Long tenantId = TenantHelper.getDynamic(); + if (ObjectUtil.isNull(tenantId)) { + tenantId = LoginHelper.getTenantId(); } return tenantId; } diff --git a/ruoyi-common/ruoyi-common-tenant/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/ruoyi-common/ruoyi-common-tenant/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 0000000..8f39d11 --- /dev/null +++ b/ruoyi-common/ruoyi-common-tenant/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +com.ruoyi.common.tenant.config.TenantConfig diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java index b1e8756..98a81be 100644 --- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java @@ -1,7 +1,5 @@ package com.ruoyi.system.mapper; -import java.util.List; - import com.mybatisflex.core.BaseMapper; import com.ruoyi.system.domain.SysPost; import org.apache.ibatis.annotations.Mapper;