add 新增 ThreadLocalHolder 替代 SaHolder 支持异步

add 新增 ThreadLocalHolder 替代 SaHolder 支持异步
2.X
疯狂的狮子Li 1 year ago
parent 77cfb9137e
commit c68eb5701b

@ -99,6 +99,11 @@
<artifactId>ip2region</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
</dependency>
</dependencies>
</project>

@ -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<Map<String, Object>> THREAD_LOCAL = TransmittableThreadLocal.withInitial(HashMap::new);
/**
*
*
* @param key
* @param value
*/
public static <T> void set(String key, T value) {
THREAD_LOCAL.get().put(key, value);
}
/**
*
*
* @param key
* @return
*/
@SuppressWarnings("unchecked")
public static <T> 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();
}
}

@ -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<RemoteDictDataVo> datas = (List<RemoteDictDataVo>) SaHolder.getStorage().get(CacheConstants.SYS_DICT_KEY + dictType);
List<RemoteDictDataVo> 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<String, String> 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<RemoteDictDataVo> datas = (List<RemoteDictDataVo>) SaHolder.getStorage().get(CacheConstants.SYS_DICT_KEY + dictType);
List<RemoteDictDataVo> 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<String, String> map = StreamUtils.toMap(datas, RemoteDictDataVo::getDictLabel, RemoteDictDataVo::getDictValue);

@ -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<String> 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);
}
/**

@ -27,11 +27,6 @@
<artifactId>ruoyi-common-json</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>

@ -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<StopWatch> 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<String, String> 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 {

@ -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<Object> 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) {

@ -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("/**");
}
/**

@ -26,11 +26,6 @@
<artifactId>ruoyi-common-redis</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
</dependency>
</dependencies>
</project>

@ -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<String> 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);
}
/**

Loading…
Cancel
Save