diff --git a/ruoyi-common/ruoyi-common-core/pom.xml b/ruoyi-common/ruoyi-common-core/pom.xml index 01d876e7..84ab453a 100644 --- a/ruoyi-common/ruoyi-common-core/pom.xml +++ b/ruoyi-common/ruoyi-common-core/pom.xml @@ -99,6 +99,11 @@ ip2region + + com.alibaba + transmittable-thread-local + + diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/context/ThreadLocalHolder.java b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/context/ThreadLocalHolder.java new file mode 100644 index 00000000..e527dab9 --- /dev/null +++ b/ruoyi-common/ruoyi-common-core/src/main/java/org/dromara/common/core/context/ThreadLocalHolder.java @@ -0,0 +1,57 @@ +package org.dromara.common.core.context; + +import com.alibaba.ttl.TransmittableThreadLocal; + +import java.util.HashMap; +import java.util.Map; + +/** + * 线程持有类 + * + * @author Michelle.Chung + */ +public class ThreadLocalHolder { + + /** + * 初始化 (支持异步) + */ + private static final ThreadLocal> THREAD_LOCAL = TransmittableThreadLocal.withInitial(HashMap::new); + + /** + * 设置值 + * + * @param key 键 + * @param value 值 + */ + public static void set(String key, T value) { + THREAD_LOCAL.get().put(key, value); + } + + /** + * 获取值 + * + * @param key 键 + * @return 值 + */ + @SuppressWarnings("unchecked") + public static T get(String key) { + return (T) THREAD_LOCAL.get().get(key); + } + + /** + * 移除值 + * + * @param key 键 + */ + public static void remove(String key) { + THREAD_LOCAL.get().remove(key); + } + + /** + * 清空值 + */ + public static void clear() { + THREAD_LOCAL.remove(); + } + +} diff --git a/ruoyi-common/ruoyi-common-dict/src/main/java/org/dromara/common/dict/service/impl/DictServiceImpl.java b/ruoyi-common/ruoyi-common-dict/src/main/java/org/dromara/common/dict/service/impl/DictServiceImpl.java index 2de6c554..1c96654b 100644 --- a/ruoyi-common/ruoyi-common-dict/src/main/java/org/dromara/common/dict/service/impl/DictServiceImpl.java +++ b/ruoyi-common/ruoyi-common-dict/src/main/java/org/dromara/common/dict/service/impl/DictServiceImpl.java @@ -1,13 +1,13 @@ package org.dromara.common.dict.service.impl; -import cn.dev33.satoken.context.SaHolder; import cn.hutool.core.util.ObjectUtil; +import org.apache.dubbo.config.annotation.DubboReference; import org.dromara.common.core.constant.CacheConstants; +import org.dromara.common.core.context.ThreadLocalHolder; import org.dromara.common.core.service.DictService; import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.system.api.RemoteDictService; -import org.apache.dubbo.config.annotation.DubboReference; import org.dromara.system.api.domain.vo.RemoteDictDataVo; import org.springframework.stereotype.Service; @@ -35,14 +35,13 @@ public class DictServiceImpl implements DictService { * @param separator 分隔符 * @return 字典标签 */ - @SuppressWarnings("unchecked cast") @Override public String getDictLabel(String dictType, String dictValue, String separator) { // 优先从本地缓存获取 - List datas = (List) SaHolder.getStorage().get(CacheConstants.SYS_DICT_KEY + dictType); + List datas = ThreadLocalHolder.get(CacheConstants.SYS_DICT_KEY + dictType); if (ObjectUtil.isNull(datas)) { datas = remoteDictService.selectDictDataByType(dictType); - SaHolder.getStorage().set(CacheConstants.SYS_DICT_KEY + dictType, datas); + ThreadLocalHolder.set(CacheConstants.SYS_DICT_KEY + dictType, datas); } Map map = StreamUtils.toMap(datas, RemoteDictDataVo::getDictValue, RemoteDictDataVo::getDictLabel); @@ -63,14 +62,13 @@ public class DictServiceImpl implements DictService { * @param separator 分隔符 * @return 字典值 */ - @SuppressWarnings("unchecked cast") @Override public String getDictValue(String dictType, String dictLabel, String separator) { // 优先从本地缓存获取 - List datas = (List) SaHolder.getStorage().get(CacheConstants.SYS_DICT_KEY + dictType); + List datas = ThreadLocalHolder.get(CacheConstants.SYS_DICT_KEY + dictType); if (ObjectUtil.isNull(datas)) { datas = remoteDictService.selectDictDataByType(dictType); - SaHolder.getStorage().set(CacheConstants.SYS_DICT_KEY + dictType, datas); + ThreadLocalHolder.set(CacheConstants.SYS_DICT_KEY + dictType, datas); } Map map = StreamUtils.toMap(datas, RemoteDictDataVo::getDictLabel, RemoteDictDataVo::getDictValue); diff --git a/ruoyi-common/ruoyi-common-idempotent/src/main/java/org/dromara/common/idempotent/aspectj/RepeatSubmitAspect.java b/ruoyi-common/ruoyi-common-idempotent/src/main/java/org/dromara/common/idempotent/aspectj/RepeatSubmitAspect.java index fc53b1b0..b3501702 100644 --- a/ruoyi-common/ruoyi-common-idempotent/src/main/java/org/dromara/common/idempotent/aspectj/RepeatSubmitAspect.java +++ b/ruoyi-common/ruoyi-common-idempotent/src/main/java/org/dromara/common/idempotent/aspectj/RepeatSubmitAspect.java @@ -5,6 +5,7 @@ import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.crypto.SecureUtil; import org.dromara.common.core.constant.GlobalConstants; +import org.dromara.common.core.context.ThreadLocalHolder; import org.dromara.common.core.domain.R; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.core.utils.MessageUtils; @@ -36,7 +37,7 @@ import java.util.StringJoiner; @Aspect public class RepeatSubmitAspect { - private static final ThreadLocal KEY_CACHE = new ThreadLocal<>(); + private static final String KEY_CACHE = "keyCache"; @Before("@annotation(repeatSubmit)") public void doBefore(JoinPoint point, RepeatSubmit repeatSubmit) throws Throwable { @@ -59,7 +60,7 @@ public class RepeatSubmitAspect { // 唯一标识(指定key + url + 消息头) String cacheRepeatKey = GlobalConstants.REPEAT_SUBMIT_KEY + url + submitKey; if (RedisUtils.setObjectIfAbsent(cacheRepeatKey, "", Duration.ofMillis(interval))) { - KEY_CACHE.set(cacheRepeatKey); + ThreadLocalHolder.set(KEY_CACHE, cacheRepeatKey); } else { String message = repeatSubmit.message(); if (StringUtils.startsWith(message, "{") && StringUtils.endsWith(message, "}")) { @@ -82,9 +83,10 @@ public class RepeatSubmitAspect { if (r.getCode() == R.SUCCESS) { return; } - RedisUtils.deleteObject(KEY_CACHE.get()); + String cacheKey = ThreadLocalHolder.get(KEY_CACHE); + RedisUtils.deleteObject(cacheKey); } finally { - KEY_CACHE.remove(); + ThreadLocalHolder.remove(KEY_CACHE); } } } @@ -97,8 +99,9 @@ public class RepeatSubmitAspect { */ @AfterThrowing(value = "@annotation(repeatSubmit)", throwing = "e") public void doAfterThrowing(JoinPoint joinPoint, RepeatSubmit repeatSubmit, Exception e) { - RedisUtils.deleteObject(KEY_CACHE.get()); - KEY_CACHE.remove(); + String cacheKey = ThreadLocalHolder.get(KEY_CACHE); + RedisUtils.deleteObject(cacheKey); + ThreadLocalHolder.remove(KEY_CACHE); } /** diff --git a/ruoyi-common/ruoyi-common-log/pom.xml b/ruoyi-common/ruoyi-common-log/pom.xml index cbda66f8..2614957f 100644 --- a/ruoyi-common/ruoyi-common-log/pom.xml +++ b/ruoyi-common/ruoyi-common-log/pom.xml @@ -27,11 +27,6 @@ ruoyi-common-json - - com.alibaba - transmittable-thread-local - - org.apache.dubbo dubbo-spring-boot-starter diff --git a/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java b/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java index 06beca6a..6b35d78d 100644 --- a/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java +++ b/ruoyi-common/ruoyi-common-log/src/main/java/org/dromara/common/log/aspect/LogAspect.java @@ -4,7 +4,6 @@ import cn.hutool.core.lang.Dict; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ObjectUtil; -import com.alibaba.ttl.TransmittableThreadLocal; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; @@ -14,6 +13,7 @@ import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; +import org.dromara.common.core.context.ThreadLocalHolder; import org.dromara.common.core.utils.ServletUtils; import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.core.utils.StringUtils; @@ -49,9 +49,9 @@ public class LogAspect { /** - * 计算操作消耗时间 + * 计时 key */ - private static final ThreadLocal TIME_THREADLOCAL = new TransmittableThreadLocal<>(); + private static final String LOG_STOP_WATCH_KEY = "logStopwatch"; /** * 处理请求前执行 @@ -59,7 +59,7 @@ public class LogAspect { @Before(value = "@annotation(controllerLog)") public void boBefore(JoinPoint joinPoint, Log controllerLog) { StopWatch stopWatch = new StopWatch(); - TIME_THREADLOCAL.set(stopWatch); + ThreadLocalHolder.set(LOG_STOP_WATCH_KEY, stopWatch); stopWatch.start(); } @@ -112,7 +112,7 @@ public class LogAspect { // 处理设置注解上的参数 getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult); // 设置消耗时间 - StopWatch stopWatch = TIME_THREADLOCAL.get(); + StopWatch stopWatch = ThreadLocalHolder.get(LOG_STOP_WATCH_KEY); stopWatch.stop(); operLog.setCostTime(stopWatch.getTime()); // 发布事件保存数据库 @@ -122,7 +122,7 @@ public class LogAspect { log.error("异常信息:{}", exp.getMessage()); exp.printStackTrace(); } finally { - TIME_THREADLOCAL.remove(); + ThreadLocalHolder.remove(LOG_STOP_WATCH_KEY); } } @@ -161,7 +161,7 @@ public class LogAspect { Map paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest()); String requestMethod = operLog.getRequestMethod(); if (MapUtil.isEmpty(paramsMap) - && HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) { + && HttpMethod.PUT.name().equals(requestMethod) || HttpMethod.POST.name().equals(requestMethod)) { String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames); operLog.setOperParam(StringUtils.substring(params, 0, 2000)); } else { diff --git a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java index 7ef120d6..b1293abc 100644 --- a/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java +++ b/ruoyi-common/ruoyi-common-satoken/src/main/java/org/dromara/common/satoken/utils/LoginHelper.java @@ -1,7 +1,5 @@ package org.dromara.common.satoken.utils; -import cn.dev33.satoken.context.SaHolder; -import cn.dev33.satoken.context.model.SaStorage; import cn.dev33.satoken.session.SaSession; import cn.dev33.satoken.stp.SaLoginModel; import cn.dev33.satoken.stp.StpUtil; @@ -11,6 +9,7 @@ import lombok.AccessLevel; import lombok.NoArgsConstructor; import org.dromara.common.core.constant.TenantConstants; import org.dromara.common.core.constant.UserConstants; +import org.dromara.common.core.context.ThreadLocalHolder; import org.dromara.common.core.enums.UserType; import org.dromara.system.api.model.LoginUser; @@ -47,11 +46,10 @@ public class LoginHelper { * @param model 配置参数 */ public static void login(LoginUser loginUser, SaLoginModel model) { - SaStorage storage = SaHolder.getStorage(); - storage.set(LOGIN_USER_KEY, loginUser); - storage.set(TENANT_KEY, loginUser.getTenantId()); - storage.set(USER_KEY, loginUser.getUserId()); - storage.set(DEPT_KEY, loginUser.getDeptId()); + ThreadLocalHolder.set(LOGIN_USER_KEY, loginUser); + ThreadLocalHolder.set(TENANT_KEY, loginUser.getTenantId()); + ThreadLocalHolder.set(USER_KEY, loginUser.getUserId()); + ThreadLocalHolder.set(DEPT_KEY, loginUser.getDeptId()); model = ObjectUtil.defaultIfNull(model, new SaLoginModel()); StpUtil.login(loginUser.getLoginId(), model.setExtra(TENANT_KEY, loginUser.getTenantId()) @@ -161,10 +159,10 @@ public class LoginHelper { public static Object getStorageIfAbsentSet(String key, Supplier handle) { try { - Object obj = SaHolder.getStorage().get(key); + Object obj = ThreadLocalHolder.get(key); if (ObjectUtil.isNull(obj)) { obj = handle.get(); - SaHolder.getStorage().set(key, obj); + ThreadLocalHolder.set(key, obj); } return obj; } catch (Exception e) { diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/org/dromara/common/security/config/SecurityConfiguration.java b/ruoyi-common/ruoyi-common-security/src/main/java/org/dromara/common/security/config/SecurityConfiguration.java index efd34fc2..2f9b49b9 100644 --- a/ruoyi-common/ruoyi-common-security/src/main/java/org/dromara/common/security/config/SecurityConfiguration.java +++ b/ruoyi-common/ruoyi-common-security/src/main/java/org/dromara/common/security/config/SecurityConfiguration.java @@ -5,7 +5,11 @@ import cn.dev33.satoken.filter.SaServletFilter; import cn.dev33.satoken.interceptor.SaInterceptor; import cn.dev33.satoken.same.SaSameUtil; import cn.dev33.satoken.util.SaResult; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.dromara.common.core.constant.HttpStatus; +import org.dromara.common.core.context.ThreadLocalHolder; +import org.dromara.common.satoken.utils.LoginHelper; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; @@ -25,7 +29,12 @@ public class SecurityConfiguration implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { // 注册路由拦截器,自定义验证规则 - registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**"); + registry.addInterceptor(new SaInterceptor() { + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { + ThreadLocalHolder.remove(LoginHelper.LOGIN_USER_KEY); + } + }).addPathPatterns("/**"); } /** diff --git a/ruoyi-common/ruoyi-common-tenant/pom.xml b/ruoyi-common/ruoyi-common-tenant/pom.xml index 2b87bf96..f94340a9 100644 --- a/ruoyi-common/ruoyi-common-tenant/pom.xml +++ b/ruoyi-common/ruoyi-common-tenant/pom.xml @@ -26,11 +26,6 @@ ruoyi-common-redis - - com.alibaba - transmittable-thread-local - - diff --git a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/helper/TenantHelper.java b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/helper/TenantHelper.java index e830c190..7a3a431c 100644 --- a/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/helper/TenantHelper.java +++ b/ruoyi-common/ruoyi-common-tenant/src/main/java/org/dromara/common/tenant/helper/TenantHelper.java @@ -1,15 +1,14 @@ package org.dromara.common.tenant.helper; -import cn.dev33.satoken.context.SaHolder; import cn.dev33.satoken.stp.StpUtil; 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 lombok.AccessLevel; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.constant.GlobalConstants; +import org.dromara.common.core.context.ThreadLocalHolder; import org.dromara.common.core.utils.SpringUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.redis.utils.RedisUtils; @@ -28,7 +27,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 String TENANT_ID_KEY = "tempDynamicTenant"; /** * 租户功能是否启用 @@ -89,12 +88,12 @@ public class TenantHelper { return; } if (!isLogin()) { - TEMP_DYNAMIC_TENANT.set(tenantId); + ThreadLocalHolder.set(TENANT_ID_KEY, tenantId); return; } String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId(); RedisUtils.setCacheObject(cacheKey, tenantId); - SaHolder.getStorage().set(cacheKey, tenantId); + ThreadLocalHolder.set(cacheKey, tenantId); } /** @@ -107,15 +106,15 @@ public class TenantHelper { return null; } if (!isLogin()) { - return TEMP_DYNAMIC_TENANT.get(); + return ThreadLocalHolder.get(TENANT_ID_KEY); } String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId(); - String tenantId = (String) SaHolder.getStorage().get(cacheKey); + String tenantId = ThreadLocalHolder.get(cacheKey); if (StringUtils.isNotBlank(tenantId)) { return tenantId; } tenantId = RedisUtils.getCacheObject(cacheKey); - SaHolder.getStorage().set(cacheKey, tenantId); + ThreadLocalHolder.set(cacheKey, tenantId); return tenantId; } @@ -127,12 +126,12 @@ public class TenantHelper { return; } if (!isLogin()) { - TEMP_DYNAMIC_TENANT.remove(); + ThreadLocalHolder.remove(TENANT_ID_KEY); return; } String cacheKey = DYNAMIC_TENANT_KEY + ":" + LoginHelper.getUserId(); RedisUtils.deleteObject(cacheKey); - SaHolder.getStorage().delete(cacheKey); + ThreadLocalHolder.remove(cacheKey); } /**