fix(uboot-core): 幂等
修复delKey = true。即业务执行完,删除key
This commit is contained in:
@ -1,7 +1,9 @@
|
|||||||
package com.chinaunicom.mall.ebtp.common.idempotent.aspect;
|
package com.chinaunicom.mall.ebtp.common.idempotent.aspect;
|
||||||
|
|
||||||
|
import com.chinaunicom.mall.ebtp.cloud.security.starter.common.Constants;
|
||||||
import com.chinaunicom.mall.ebtp.common.exception.common.CommonExceptionEnum;
|
import com.chinaunicom.mall.ebtp.common.exception.common.CommonExceptionEnum;
|
||||||
import com.chinaunicom.mall.ebtp.common.idempotent.annotation.Idempotent;
|
import com.chinaunicom.mall.ebtp.common.idempotent.annotation.Idempotent;
|
||||||
|
import com.chinaunicom.mall.ebtp.common.util.HttpContextUtils;
|
||||||
import com.chinaunicom.mall.ebtp.common.util.JsonUtils;
|
import com.chinaunicom.mall.ebtp.common.util.JsonUtils;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.aspectj.lang.JoinPoint;
|
import org.aspectj.lang.JoinPoint;
|
||||||
@ -13,16 +15,11 @@ import org.aspectj.lang.reflect.MethodSignature;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.data.redis.core.RedisTemplate;
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.CollectionUtils;
|
|
||||||
import org.springframework.web.context.request.RequestContextHolder;
|
|
||||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -35,14 +32,6 @@ import java.util.concurrent.TimeUnit;
|
|||||||
@Aspect
|
@Aspect
|
||||||
public class IdempotentAspect {
|
public class IdempotentAspect {
|
||||||
|
|
||||||
private static final ThreadLocal<Map<String, Object>> THREAD_CACHE = ThreadLocal.withInitial(HashMap::new);
|
|
||||||
|
|
||||||
private static final String RMAPCACHE_KEY = "idempotent";
|
|
||||||
|
|
||||||
private static final String KEY = "key";
|
|
||||||
|
|
||||||
private static final String DELKEY = "delKey";
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedisTemplate<String, Object> redisTemplate;
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
@ -52,10 +41,8 @@ public class IdempotentAspect {
|
|||||||
|
|
||||||
@Before("pointCut()")
|
@Before("pointCut()")
|
||||||
public void beforePointCut(JoinPoint joinPoint) {
|
public void beforePointCut(JoinPoint joinPoint) {
|
||||||
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
|
|
||||||
.getRequestAttributes();
|
HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
|
||||||
assert requestAttributes != null;
|
|
||||||
HttpServletRequest request = requestAttributes.getRequest();
|
|
||||||
|
|
||||||
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
|
||||||
Method method = signature.getMethod();
|
Method method = signature.getMethod();
|
||||||
@ -64,12 +51,7 @@ public class IdempotentAspect {
|
|||||||
}
|
}
|
||||||
Idempotent idempotent = method.getAnnotation(Idempotent.class);
|
Idempotent idempotent = method.getAnnotation(Idempotent.class);
|
||||||
|
|
||||||
/* key : url + 参数列表作为区分 */
|
String key = getKey(joinPoint, request);
|
||||||
String url = request.getRequestURL().toString();
|
|
||||||
String argString = JsonUtils.objectToJson(Arrays.asList(joinPoint.getArgs()));
|
|
||||||
assert argString != null;
|
|
||||||
String redisKey = String.valueOf(argString.hashCode());
|
|
||||||
String key = url.concat(":").concat(redisKey);
|
|
||||||
|
|
||||||
long expireTime = idempotent.expireTime();
|
long expireTime = idempotent.expireTime();
|
||||||
String info = idempotent.info();
|
String info = idempotent.info();
|
||||||
@ -77,47 +59,49 @@ public class IdempotentAspect {
|
|||||||
boolean delKey = idempotent.delKey();
|
boolean delKey = idempotent.delKey();
|
||||||
|
|
||||||
// do not need check null
|
// do not need check null
|
||||||
Map<Object, Object> rMapCache = redisTemplate.opsForHash().entries(RMAPCACHE_KEY);
|
Object o = redisTemplate.opsForValue().get(key);
|
||||||
String value = LocalDateTime.now().toString().replace("T", " ");
|
if (null != o) {
|
||||||
if (null != rMapCache.get(key)) {
|
|
||||||
// had stored
|
// had stored
|
||||||
CommonExceptionEnum.FRAME_EXCEPTION_COMMON_DATA_OTHER_ERROR.customValidName(info, true);
|
CommonExceptionEnum.FRAME_EXCEPTION_COMMON_DATA_OTHER_ERROR.customValidName(info, true);
|
||||||
}
|
}
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
boolean submitAble = redisTemplate.opsForValue().setIfAbsent(key, value, expireTime, timeUnit);
|
boolean submitAble = redisTemplate.opsForValue().setIfAbsent(key, delKey, expireTime, timeUnit);
|
||||||
if (!submitAble) {
|
if (!submitAble) {
|
||||||
CommonExceptionEnum.FRAME_EXCEPTION_COMMON_DATA_OTHER_ERROR.customValidName(info, true);
|
CommonExceptionEnum.FRAME_EXCEPTION_COMMON_DATA_OTHER_ERROR.customValidName(info, true);
|
||||||
} else {
|
} else {
|
||||||
log.info("[idempotent]:has stored key={},value={},expireTime={}{},now={}", key, value, expireTime,
|
log.info("[idempotent]:has stored key={},value={},expireTime={}{},now={}", key, delKey, expireTime,
|
||||||
timeUnit, LocalDateTime.now().toString());
|
timeUnit, LocalDateTime.now());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, Object> map = THREAD_CACHE.get();
|
}
|
||||||
map.put(KEY, key);
|
|
||||||
map.put(DELKEY, delKey);
|
private String getKey(JoinPoint joinPoint, HttpServletRequest request) {
|
||||||
|
String token = request.getHeader(Constants.AUTHORIZATION_HEADER);
|
||||||
|
/* key : token + url + 参数列表作为区分 */
|
||||||
|
String url = request.getRequestURI();
|
||||||
|
String argString = JsonUtils.objectToJson(Arrays.asList(joinPoint.getArgs()));
|
||||||
|
assert argString != null;
|
||||||
|
String redisKey = String.valueOf(argString.hashCode());
|
||||||
|
return token.concat(":").concat(url).concat(":").concat(redisKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@After("pointCut()")
|
@After("pointCut()")
|
||||||
public void afterPointCut(JoinPoint joinPoint) {
|
public void afterPointCut(JoinPoint joinPoint) {
|
||||||
Map<String, Object> map = THREAD_CACHE.get();
|
HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
|
||||||
if (CollectionUtils.isEmpty(map)) {
|
String key = getKey(joinPoint, request);
|
||||||
|
|
||||||
|
Object o = redisTemplate.opsForValue().get(key);
|
||||||
|
if (o == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<Object, Object> mapCache = redisTemplate.opsForHash().entries(RMAPCACHE_KEY);
|
boolean delKey = (boolean) o;
|
||||||
if (mapCache.size() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String key = map.get(KEY).toString();
|
|
||||||
boolean delKey = (boolean) map.get(DELKEY);
|
|
||||||
|
|
||||||
if (delKey) {
|
if (delKey) {
|
||||||
mapCache.remove(key);
|
redisTemplate.delete(key);
|
||||||
log.info("[idempotent]:has removed key={}", key);
|
log.info("[idempotent]:has removed key={}", key);
|
||||||
}
|
}
|
||||||
THREAD_CACHE.remove();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user