This commit is contained in:
77
2024-05-18 01:02:13 +08:00
parent 874b33557d
commit 32933c2840
47 changed files with 416 additions and 282 deletions

View File

@@ -80,5 +80,9 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
</dependency>
</dependencies>
</project>

View File

@@ -25,10 +25,9 @@ import java.util.concurrent.ThreadPoolExecutor;
public class ThreadPoolConfig {
/**
* 核心线程数 = cpu 核心数 + 1
* 核心线程数 = cpu 核心数 + 1 TODO 线程池
*/
// private final int core = Runtime.getRuntime().availableProcessors() + 1;
private final int core = 6 + 1;
private final int core = Runtime.getRuntime().availableProcessors() + 1;
@Bean(name = "threadPoolTaskExecutor")

View File

@@ -12,38 +12,4 @@ public interface CacheConstants {
*/
String ONLINE_TOKEN_KEY = "online_tokens:";
/**
* 单天在线APP用户
*/
String ONLINE_TODAY_TOKEN_KEY = "online_tokens_today:%s";
/**
* 验证码 redis key
*/
String CAPTCHA_CODE_KEY = "captcha_codes:";
/**
* 参数管理 cache key
*/
String SYS_CONFIG_KEY = "sys_config:";
/**
* 字典管理 cache key
*/
String SYS_DICT_KEY = "sys_dict:";
/**
* 防重提交 redis key
*/
String REPEAT_SUBMIT_KEY = "repeat_submit:";
/**
* 限流 redis key
*/
String RATE_LIMIT_KEY = "rate_limit:";
/**
* 登录账户密码错误次数 redis key
*/
String PWD_ERR_CNT_KEY = "pwd_err_cnt:";
}

View File

@@ -15,20 +15,15 @@ package com.ruoyi.component.core.constant;
*/
public interface CacheNames {
/**
* 演示案例
*/
String DEMO_CACHE = "demo:cache#60s#10m#20";
/**
* 系统配置
*/
String SYS_CONFIG = "sys_config";
String SYS_CONFIG = GlobalConstants.GLOBAL_REDIS_KEY + "sys_config";
/**
* 数据字典
*/
String SYS_DICT = "sys_dict";
String SYS_DICT = GlobalConstants.GLOBAL_REDIS_KEY + "sys_dict";
/**
* 用户账户
@@ -52,9 +47,4 @@ public interface CacheNames {
*/
String SYS_OSS_CONFIG = GlobalConstants.GLOBAL_REDIS_KEY + "sys_oss_config";
/**
* 在线用户
*/
String ONLINE_TOKEN = "online_tokens";
}

View File

@@ -36,4 +36,14 @@ public interface GlobalConstants {
* 三方认证 redis key
*/
String SOCIAL_AUTH_CODE_KEY = GLOBAL_REDIS_KEY + "social_auth_codes:";
/**
* 字典管理 cache key
*/
String SYS_DICT_KEY = GLOBAL_REDIS_KEY + "sys_dict:";
/**
* 参数管理 cache key
*/
String SYS_CONFIG_KEY = GLOBAL_REDIS_KEY + "sys_config:";
}

View File

@@ -139,9 +139,4 @@ public interface UserConstants {
*/
Long ADMIN_ID = 1L;
/**
* 管理员角色key
*/
String ADMIN_ROLE_KEY = "admin";
}

View File

@@ -100,6 +100,8 @@ public class LoginUser implements Serializable {
*/
private Long roleId;
private String tenantId;
/**
* 获取登录id
*/

View File

@@ -0,0 +1,34 @@
package com.ruoyi.component.core.executor;
import com.alibaba.ttl.threadpool.TtlExecutors;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.util.concurrent.*;
public class ExecutorConstant {
private final static int CPU_NUM = Runtime.getRuntime().availableProcessors();
public static Executor COMMON_EXECUTOR;
static {
ThreadPoolExecutor commonExecutor = new ThreadPoolExecutor(CPU_NUM,
CPU_NUM << 2,
5,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(50),
init("commonThreadPool-%d"),
new ThreadPoolExecutor.CallerRunsPolicy());
COMMON_EXECUTOR = TtlExecutors.getTtlExecutor(commonExecutor);
}
private static ThreadFactory init(String nameFormat){
return new ThreadFactoryBuilder().setNameFormat(nameFormat).build();
}
private static ThreadPoolExecutor initExecutor(int corePoolSize, int maxPoolSize, int keepAliveTime, TimeUnit timeUnit,
BlockingQueue<Runnable> workQueue, String nameFormat){
return new ThreadPoolExecutor(corePoolSize, maxPoolSize, keepAliveTime, timeUnit, workQueue,
init(nameFormat));
}
}

View File

@@ -30,7 +30,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</resultMap>
<select id="selectDbTableColumnsByName" parameterType="String" resultMap="GenTableColumnResult">
<if test="@com.ruoyi.common.helper.DataBaseHelper@isMySql()">
<if test="@com.ruoyi.component.mybatis.helper.DataBaseHelper@isMySql()">
select column_name,
(case when (is_nullable = 'no' <![CDATA[ && ]]> column_key != 'PRI') then '1' else '0' end) as is_required,
(case when column_key = 'PRI' then '1' else '0' end) as is_pk,
@@ -41,7 +41,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
from information_schema.columns where table_schema = (select database()) and table_name = (#{tableName})
order by ordinal_position
</if>
<if test="@com.ruoyi.common.helper.DataBaseHelper@isOracle()">
<if test="@com.ruoyi.component.mybatis.helper.DataBaseHelper@isOracle()">
select lower(temp.column_name) as column_name,
(case when (temp.nullable = 'N' and temp.constraint_type != 'P') then '1' else '0' end) as is_required,
(case when temp.constraint_type = 'P' then '1' else '0' end) as is_pk,
@@ -61,7 +61,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
WHERE temp.row_flg = 1
ORDER BY temp.column_id
</if>
<if test="@com.ruoyi.common.helper.DataBaseHelper@isPostgerSql()">
<if test="@com.ruoyi.component.mybatis.helper.DataBaseHelper@isPostgerSql()">
SELECT column_name, is_required, is_pk, sort, column_comment, is_increment, column_type
FROM (
SELECT c.relname AS table_name,
@@ -95,7 +95,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
WHERE table_name = (#{tableName})
AND column_type <![CDATA[ <> ]]> '-'
</if>
<if test="@com.ruoyi.common.helper.DataBaseHelper@isSqlServer()">
<if test="@com.ruoyi.component.mybatis.helper.DataBaseHelper@isSqlServer()">
SELECT
cast(A.NAME as nvarchar) as column_name,
cast(B.NAME as nvarchar) + (case when B.NAME = 'numeric' then '(' + cast(A.prec as nvarchar) + ',' + cast(A.scale as nvarchar) + ')' else '' end) as column_type,

View File

@@ -54,7 +54,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</resultMap>
<select id="selectPageDbTableList" resultMap="GenTableResult">
<if test="@com.ruoyi.common.helper.DataBaseHelper@isMySql()">
<if test="@com.ruoyi.component.mybatis.helper.DataBaseHelper@isMySql()">
select table_name, table_comment, create_time, update_time
from information_schema.tables
where table_schema = (select database())
@@ -68,7 +68,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</if>
order by create_time desc
</if>
<if test="@com.ruoyi.common.helper.DataBaseHelper@isOracle()">
<if test="@com.ruoyi.component.mybatis.helper.DataBaseHelper@isOracle()">
select lower(dt.table_name) as table_name, dtc.comments as table_comment, uo.created as create_time, uo.last_ddl_time as update_time
from user_tables dt, user_tab_comments dtc, user_objects uo
where dt.table_name = dtc.table_name
@@ -84,7 +84,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</if>
order by create_time desc
</if>
<if test="@com.ruoyi.common.helper.DataBaseHelper@isPostgerSql()">
<if test="@com.ruoyi.component.mybatis.helper.DataBaseHelper@isPostgerSql()">
select table_name, table_comment, create_time, update_time
from (
SELECT c.relname AS table_name,
@@ -108,7 +108,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</if>
order by create_time desc
</if>
<if test="@com.ruoyi.common.helper.DataBaseHelper@isSqlServer()">
<if test="@com.ruoyi.component.mybatis.helper.DataBaseHelper@isSqlServer()">
SELECT cast(D.NAME as nvarchar) as table_name,
cast(F.VALUE as nvarchar) as table_comment,
crdate as create_time,
@@ -129,7 +129,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</select>
<select id="selectDbTableListByNames" resultMap="GenTableResult">
<if test="@com.ruoyi.common.helper.DataBaseHelper@isMySql()">
<if test="@com.ruoyi.component.mybatis.helper.DataBaseHelper@isMySql()">
select table_name, table_comment, create_time, update_time from information_schema.tables
where table_name NOT LIKE 'xxl_job_%' and table_name NOT LIKE 'gen_%' and table_schema = (select database())
and table_name in
@@ -137,7 +137,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{name}
</foreach>
</if>
<if test="@com.ruoyi.common.helper.DataBaseHelper@isOracle()">
<if test="@com.ruoyi.component.mybatis.helper.DataBaseHelper@isOracle()">
select lower(dt.table_name) as table_name, dtc.comments as table_comment, uo.created as create_time, uo.last_ddl_time as update_time
from user_tables dt, user_tab_comments dtc, user_objects uo
where dt.table_name = dtc.table_name
@@ -150,7 +150,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{name}
</foreach>
</if>
<if test="@com.ruoyi.common.helper.DataBaseHelper@isPostgerSql()">
<if test="@com.ruoyi.component.mybatis.helper.DataBaseHelper@isPostgerSql()">
select table_name, table_comment, create_time, update_time
from (
SELECT c.relname AS table_name,
@@ -170,7 +170,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{name}
</foreach>
</if>
<if test="@com.ruoyi.common.helper.DataBaseHelper@isSqlServer()">
<if test="@com.ruoyi.component.mybatis.helper.DataBaseHelper@isSqlServer()">
SELECT cast(D.NAME as nvarchar) as table_name,
cast(F.VALUE as nvarchar) as table_comment,
crdate as create_time,
@@ -187,12 +187,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</select>
<select id="selectTableByName" parameterType="String" resultMap="GenTableResult">
<if test="@com.ruoyi.common.helper.DataBaseHelper@isMySql()">
<if test="@com.ruoyi.component.mybatis.helper.DataBaseHelper@isMySql()">
select table_name, table_comment, create_time, update_time from information_schema.tables
where table_name NOT LIKE 'xxl_job_%' and table_name NOT LIKE 'gen_%' and table_schema = (select database())
and table_name = #{tableName}
</if>
<if test="@com.ruoyi.common.helper.DataBaseHelper@isOracle()">
<if test="@com.ruoyi.component.mybatis.helper.DataBaseHelper@isOracle()">
select lower(dt.table_name) as table_name, dtc.comments as table_comment, uo.created as create_time, uo.last_ddl_time as update_time
from user_tables dt, user_tab_comments dtc, user_objects uo
where dt.table_name = dtc.table_name
@@ -202,7 +202,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
AND dt.table_name NOT IN (select table_name from gen_table)
and lower(dt.table_name) = #{tableName}
</if>
<if test="@com.ruoyi.common.helper.DataBaseHelper@isPostgerSql()">
<if test="@com.ruoyi.component.mybatis.helper.DataBaseHelper@isPostgerSql()">
select table_name, table_comment, create_time, update_time
from (
SELECT c.relname AS table_name,
@@ -219,7 +219,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
where table_name NOT LIKE 'xxl_job_%' and table_name NOT LIKE 'gen_%'
and table_name = #{tableName}
</if>
<if test="@com.ruoyi.common.helper.DataBaseHelper@isSqlServer()">
<if test="@com.ruoyi.component.mybatis.helper.DataBaseHelper@isSqlServer()">
SELECT cast(D.NAME as nvarchar) as table_name,
cast(F.VALUE as nvarchar) as table_comment,
crdate as create_time,

View File

@@ -5,6 +5,7 @@ import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.crypto.SecureUtil;
import com.ruoyi.component.core.constant.CacheConstants;
import com.ruoyi.component.core.constant.GlobalConstants;
import com.ruoyi.component.core.domain.R;
import com.ruoyi.component.core.exception.ServiceException;
import com.ruoyi.component.core.util.MessageUtils;
@@ -57,7 +58,7 @@ public class RepeatSubmitAspect {
submitKey = SecureUtil.md5(submitKey + ":" + nowParams);
// 唯一标识指定key + url + 消息头)
String cacheRepeatKey = CacheConstants.REPEAT_SUBMIT_KEY + url + submitKey;
String cacheRepeatKey = GlobalConstants.REPEAT_SUBMIT_KEY + url + submitKey;
if (RedisUtils.setObjectIfAbsent(cacheRepeatKey, "", Duration.ofMillis(interval))) {
KEY_CACHE.set(cacheRepeatKey);
} else {

View File

@@ -1,5 +1,7 @@
package com.ruoyi.component.oss.constant;
import com.ruoyi.component.core.constant.GlobalConstants;
import java.util.Arrays;
import java.util.List;
@@ -13,7 +15,7 @@ public interface OssConstant {
/**
* 默认配置KEY
*/
String DEFAULT_CONFIG_KEY = "sys_oss:default_config";
String DEFAULT_CONFIG_KEY = GlobalConstants.GLOBAL_REDIS_KEY + "sys_oss:default_config";
/**
* 预览列表资源开关Key

View File

@@ -2,6 +2,7 @@ package com.ruoyi.component.ratelimiter.aspectj;
import cn.hutool.core.util.ArrayUtil;
import com.ruoyi.component.core.constant.CacheConstants;
import com.ruoyi.component.core.constant.GlobalConstants;
import com.ruoyi.component.core.exception.ServiceException;
import com.ruoyi.component.core.util.MessageUtils;
import com.ruoyi.component.core.util.ServletUtils;
@@ -113,7 +114,7 @@ public class RateLimiterAspect {
throw new ServiceException("限流key解析异常!请联系管理员!");
}
}
StringBuilder stringBuffer = new StringBuilder(CacheConstants.RATE_LIMIT_KEY);
StringBuilder stringBuffer = new StringBuilder(GlobalConstants.RATE_LIMIT_KEY);
stringBuffer.append(ServletUtils.getRequest().getRequestURI()).append(":");
if (rateLimiter.limitType() == LimitType.IP) {
// 获取请求ip

View File

@@ -35,9 +35,11 @@ public class LoginHelper {
public static final String LOGIN_USER_KEY = "loginUser";
public static final String USER_KEY = "userId";
public static final String TENANT_KEY = "tenantId";
public static String getTenantIdByToken(String token) {
return Convert.toStr(StpUtil.getExtra(token,TENANT_KEY));
}
/**
* 获取租户ID
@@ -83,6 +85,7 @@ public class LoginHelper {
SaStorage storage = SaHolder.getStorage();
storage.set(LOGIN_USER_KEY, loginUser);
storage.set(USER_KEY, loginUser.getUserId());
storage.set(TENANT_KEY, loginUser.getTenantId());
SaLoginModel model = new SaLoginModel();
if (ObjectUtil.isNotNull(deviceType)) {
model.setDevice(deviceType.getDevice());
@@ -95,7 +98,9 @@ public class LoginHelper {
// } else if (userType == UserType.APP_USER) {
// model.setTimeout(86400).setActiveTimeout(1800);
// }
StpUtil.login(loginUser.getLoginId(), model.setExtra(USER_KEY, loginUser.getUserId()));
model.setExtra(USER_KEY, loginUser.getUserId());
model.setExtra(TENANT_KEY,loginUser.getTenantId());
StpUtil.login(loginUser.getLoginId(), model);
StpUtil.getTokenSession().set(LOGIN_USER_KEY, loginUser);
}

View File

@@ -4,7 +4,9 @@ import cn.dev33.satoken.exception.NotLoginException;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.router.SaRouter;
import cn.dev33.satoken.stp.StpUtil;
import com.ruoyi.component.core.util.ServletUtils;
import com.ruoyi.component.core.util.spring.SpringUtils;
import com.ruoyi.component.satoken.utils.LoginHelper;
import com.ruoyi.component.security.config.properties.SecurityProperties;
import com.ruoyi.component.security.handler.AllUrlHandler;
import lombok.RequiredArgsConstructor;
@@ -44,24 +46,6 @@ public class SecurityConfig implements WebMvcConfigurer {
.check(() -> {
// 检查是否登录 是否有token
StpUtil.checkLogin();
// 检查 header 与 param 里的 clientid 与 token 里的是否一致 TODO
// String headerCid = ServletUtils.getRequest().getHeader(LoginHelper.CLIENT_KEY);
// String paramCid = ServletUtils.getParameter(LoginHelper.CLIENT_KEY);
// String clientId = StpUtil.getExtra(LoginHelper.CLIENT_KEY).toString();
// if (!StringUtils.equalsAny(clientId, headerCid, paramCid)) {
// // token 无效
// throw NotLoginException.newInstance(StpUtil.getLoginType(),
// "-100", "客户端ID与Token不匹配",
// StpUtil.getTokenValue());
// }
// 有效率影响 用于临时测试
// if (log.isDebugEnabled()) {
// log.info("剩余有效时间: {}", StpUtil.getTokenTimeout());
// log.info("临时有效时间: {}", StpUtil.getTokenActivityTimeout());
// }
});
})).addPathPatterns("/**")
// 排除不需要拦截的路径

View File

@@ -10,6 +10,7 @@ import com.ruoyi.component.mybatis.config.MybatisPlusConfig;
import com.ruoyi.component.redis.config.RedisConfig;
import com.ruoyi.component.redis.properties.RedissonProperties;
import com.ruoyi.component.tenant.core.TenantSaTokenDao;
import com.ruoyi.component.tenant.filter.TenantFilter;
import com.ruoyi.component.tenant.handle.PlusTenantLineHandler;
import com.ruoyi.component.tenant.handle.TenantKeyPrefixHandler;
import com.ruoyi.component.tenant.manager.TenantSpringCacheManager;
@@ -20,6 +21,7 @@ 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.boot.web.servlet.FilterRegistrationBean;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
@@ -88,6 +90,17 @@ public class TenantConfig {
return new TenantSpringCacheManager();
}
@SuppressWarnings({"rawtypes", "unchecked"})
@Bean
public FilterRegistrationBean tenantFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new TenantFilter());
registration.addUrlPatterns("/*");
registration.setName("tenantFilter");
registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE);
return registration;
}
/**
* 多租户鉴权dao实现
*/

View File

@@ -0,0 +1,86 @@
package com.ruoyi.component.tenant.filter;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.ruoyi.component.core.constant.TenantConstants;
import com.ruoyi.component.core.domain.R;
import com.ruoyi.component.core.util.ServletUtils;
import com.ruoyi.component.core.util.StringUtils;
import com.ruoyi.component.satoken.utils.LoginHelper;
import com.ruoyi.component.tenant.helper.TenantHelper;
import org.springframework.util.AntPathMatcher;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
public class TenantFilter implements Filter {
public static final String TENANT_ID_HEADER = "Tenant-ID";
private static final Set<String> IGNORE_URL = new HashSet<>();
static {
IGNORE_URL.add("/login");
IGNORE_URL.add("/captchaImage");
}
private static final AntPathMatcher ANT_PATH_MATCHER = new AntPathMatcher();
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
if(!(servletRequest instanceof HttpServletRequest)){
filterChain.doFilter(servletRequest, servletResponse);
return;
}
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
try {
String requestURI = request.getRequestURI();
for (String ignoreUrlMatch : IGNORE_URL) {
boolean match = ANT_PATH_MATCHER.match(ignoreUrlMatch, requestURI);
if(match){
filterChain.doFilter(servletRequest, servletResponse);
return;
}
}
String tenantHeader = request.getHeader(TENANT_ID_HEADER);
boolean login = TenantHelper.isLogin();
if(login){
Long userId = LoginHelper.getUserId();
if(TenantConstants.SUPER_ADMIN_ID.equals(userId)){
TenantHelper.setTenantId(tenantHeader);
filterChain.doFilter(servletRequest, servletResponse);
return;
}
}
if(!StringUtils.isBlank(tenantHeader)){
if(login){
String tenantId = LoginHelper.getTenantId();
if(tenantId == null || !tenantId.equals(tenantHeader)){
ServletUtils.renderString(response, JSONUtil.toJsonStr(R.fail("平台错误")));
return;
}
TenantHelper.setTenantId(tenantId);
}else{
TenantHelper.setTenantId(tenantHeader);
}
} else {
if(login){
String tenantId = LoginHelper.getTenantId();
if(tenantId == null){
ServletUtils.renderString(response, JSONUtil.toJsonStr(R.fail("平台错误")));
return;
}
TenantHelper.setTenantId(tenantId);
}
}
filterChain.doFilter(servletRequest, servletResponse);
} finally {
TenantHelper.clearTenant();
}
}
}

View File

@@ -2,6 +2,7 @@ package com.ruoyi.component.tenant.handle;
import cn.hutool.core.collection.ListUtil;
import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.ruoyi.component.core.exception.ServiceException;
import com.ruoyi.component.core.util.StringUtils;
import com.ruoyi.component.tenant.helper.TenantHelper;
import com.ruoyi.component.tenant.properties.TenantProperties;
@@ -29,7 +30,8 @@ public class PlusTenantLineHandler implements TenantLineHandler {
String tenantId = TenantHelper.getTenantId();
if (StringUtils.isBlank(tenantId)) {
log.error("无法获取有效的租户id -> Null");
return new NullValue();
throw new ServiceException("无法获取有效的平台");
// return new NullValue();
}
// 返回固定租户
return new StringValue(tenantId);
@@ -37,20 +39,15 @@ public class PlusTenantLineHandler implements TenantLineHandler {
@Override
public boolean ignoreTable(String tableName) {
String tenantId = TenantHelper.getTenantId();
// 判断是否有租户
if (StringUtils.isNotBlank(tenantId)) {
// 不需要过滤租户的表
List<String> excludes = tenantProperties.getExcludes();
// 非业务表
List<String> tables = ListUtil.toList(
"gen_table",
"gen_table_column"
);
tables.addAll(excludes);
return tables.contains(tableName);
}
return true;
// 不需要过滤租户的表
List<String> excludes = tenantProperties.getExcludes();
// 非业务表
List<String> tables = ListUtil.toList(
"gen_table",
"gen_table_column"
);
tables.addAll(excludes);
return tables.contains(tableName);
}
}

View File

@@ -1,6 +1,7 @@
package com.ruoyi.component.tenant.handle;
import com.ruoyi.component.core.constant.GlobalConstants;
import com.ruoyi.component.core.exception.ServiceException;
import com.ruoyi.component.core.util.StringUtils;
import com.ruoyi.component.redis.handler.KeyPrefixHandler;
import com.ruoyi.component.tenant.helper.TenantHelper;
@@ -32,6 +33,7 @@ public class TenantKeyPrefixHandler extends KeyPrefixHandler {
String tenantId = TenantHelper.getTenantId();
if (StringUtils.isBlank(tenantId)) {
log.error("无法获取有效的租户id -> Null");
throw new ServiceException("无法获取有效的平台");
}
if (StringUtils.startsWith(name, tenantId + "")) {
// 如果存在则直接返回
@@ -55,6 +57,7 @@ public class TenantKeyPrefixHandler extends KeyPrefixHandler {
String tenantId = TenantHelper.getTenantId();
if (StringUtils.isBlank(tenantId)) {
log.error("无法获取有效的租户id -> Null");
throw new ServiceException("无法获取有效的平台");
}
if (StringUtils.startsWith(unmap, tenantId + "")) {
// 如果存在则删除

View File

@@ -6,11 +6,10 @@ import cn.hutool.core.convert.Convert;
import com.alibaba.ttl.TransmittableThreadLocal;
import com.baomidou.mybatisplus.core.plugins.IgnoreStrategy;
import com.baomidou.mybatisplus.core.plugins.InterceptorIgnoreHelper;
import com.ruoyi.component.satoken.utils.LoginHelper;
import com.ruoyi.component.core.constant.GlobalConstants;
import com.ruoyi.component.core.util.StringUtils;
import com.ruoyi.component.core.util.spring.SpringUtils;
import com.ruoyi.component.redis.util.RedisUtils;
import com.ruoyi.component.satoken.utils.LoginHelper;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -26,10 +25,7 @@ import java.util.function.Supplier;
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class TenantHelper {
private static final String DYNAMIC_TENANT_KEY = GlobalConstants.GLOBAL_REDIS_KEY + "dynamicTenant";
private static final ThreadLocal<String> TEMP_DYNAMIC_TENANT = new TransmittableThreadLocal<>();
private static final ThreadLocal<String> DYNAMIC_TENANT = new TransmittableThreadLocal<>();
/**
* 租户功能是否启用
*/
@@ -79,22 +75,11 @@ public class TenantHelper {
}
}
/**
* 设置动态租户(一直有效 需要手动清理)
* <p>
* 如果为未登录状态下 那么只在当前线程内生效
*/
public static void setDynamic(String tenantId) {
public static void setTenantId(String tenantId) {
if (!isEnable()) {
return;
}
if (!isLogin()) {
TEMP_DYNAMIC_TENANT.set(tenantId);
return;
}
String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId();
RedisUtils.setCacheObject(cacheKey, tenantId);
SaHolder.getStorage().set(cacheKey, tenantId);
DYNAMIC_TENANT.set(tenantId);
}
/**
@@ -102,37 +87,21 @@ public class TenantHelper {
* <p>
* 如果为未登录状态下 那么只在当前线程内生效
*/
public static String getDynamic() {
public static String getTenantId() {
if (!isEnable()) {
return null;
}
if (!isLogin()) {
return TEMP_DYNAMIC_TENANT.get();
}
String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId();
String tenantId = (String) SaHolder.getStorage().get(cacheKey);
if (StringUtils.isNotBlank(tenantId)) {
return tenantId;
}
tenantId = RedisUtils.getCacheObject(cacheKey);
SaHolder.getStorage().set(cacheKey, tenantId);
return tenantId;
return DYNAMIC_TENANT.get();
}
/**
* 清除动态租户
*/
public static void clearDynamic() {
public static void clearTenant() {
if (!isEnable()) {
return;
}
if (!isLogin()) {
TEMP_DYNAMIC_TENANT.remove();
return;
}
String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId();
RedisUtils.deleteObject(cacheKey);
SaHolder.getStorage().delete(cacheKey);
DYNAMIC_TENANT.remove();
}
/**
@@ -141,11 +110,11 @@ public class TenantHelper {
* @param handle 处理执行方法
*/
public static void dynamic(String tenantId, Runnable handle) {
setDynamic(tenantId);
setTenantId(tenantId);
try {
handle.run();
} finally {
clearDynamic();
clearTenant();
}
}
@@ -155,29 +124,15 @@ public class TenantHelper {
* @param handle 处理执行方法
*/
public static <T> T dynamic(String tenantId, Supplier<T> handle) {
setDynamic(tenantId);
setTenantId(tenantId);
try {
return handle.get();
} finally {
clearDynamic();
clearTenant();
}
}
/**
* 获取当前租户id(动态租户优先)
*/
public static String getTenantId() {
if (!isEnable()) {
return null;
}
String tenantId = TenantHelper.getDynamic();
if (StringUtils.isBlank(tenantId)) {
tenantId = LoginHelper.getTenantId();
}
return tenantId;
}
private static boolean isLogin() {
public static boolean isLogin() {
try {
StpUtil.checkLogin();
return true;