refactor(common-idempotent): 幂等插件重构@Idempotent默认值

默认执行完后删除key

修改默认错误信息格式

(cherry picked from commit 62d2087eb002d6ac5163dd6d569b35ee72b765f0)
This commit is contained in:
冷冷 committed 2024-08-16 15:11:17 +08:00
1 parent 2a1a7880f0
commit 04af734d83
3 files changed
+100 -97

No files matched your search

@@ -3,6 +3,7 @@ package com.pig4cloud.pigx.common.idempotent;
import com.pig4cloud.pigx.common.idempotent.aspect.IdempotentAspect;
import com.pig4cloud.pigx.common.idempotent.expression.ExpressionResolver;
import com.pig4cloud.pigx.common.idempotent.expression.KeyResolver;
import org.redisson.Redisson;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
@@ -19,23 +20,28 @@ import org.springframework.context.annotation.Configuration;
@AutoConfigureAfter(RedisAutoConfiguration.class)
public class IdempotentAutoConfiguration {
/**
* 切面 拦截处理所有 @Idempotent
* @return Aspect
*/
@Bean
public IdempotentAspect idempotentAspect() {
return new IdempotentAspect();
}
/**
* key 解析器
* @return KeyResolver
*/
@Bean
@ConditionalOnMissingBean(KeyResolver.class)
public KeyResolver keyResolver() {
return new ExpressionResolver();
}
/**
* KEY解析器
*
* @return {@link KeyResolver }
*/
@Bean
@ConditionalOnMissingBean(KeyResolver.class)
public KeyResolver keyResolver() {
return new ExpressionResolver();
}
/**
* 幂等方面
*
* @param redisson redisson 客户端
* @param keyResolver KEY解析器
* @return {@link IdempotentAspect }
*/
@Bean
public IdempotentAspect idempotentAspect(Redisson redisson, KeyResolver keyResolver) {
return new IdempotentAspect(redisson, keyResolver);
}
}
@@ -39,6 +39,6 @@ public @interface Idempotent {
* 是否在业务完成后删除key true:删除 false:不删除
* @return boolean
*/
boolean delKey() default false;
boolean delKey() default true;
}
@@ -4,6 +4,7 @@ import com.pig4cloud.pigx.common.idempotent.annotation.Idempotent;
import com.pig4cloud.pigx.common.idempotent.exception.IdempotentException;
import com.pig4cloud.pigx.common.idempotent.expression.KeyResolver;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
@@ -14,7 +15,6 @@ import org.redisson.Redisson;
import org.redisson.api.RMapCache;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
@@ -33,103 +33,100 @@ import java.util.concurrent.TimeUnit;
* @author ITyunqing
*/
@Aspect
@RequiredArgsConstructor
public class IdempotentAspect {
private static final Logger LOGGER = LoggerFactory.getLogger(IdempotentAspect.class);
private static final Logger LOGGER = LoggerFactory.getLogger(IdempotentAspect.class);
private static final ThreadLocal<Map<String, Object>> THREAD_CACHE = ThreadLocal.withInitial(HashMap::new);
private static final ThreadLocal<Map<String, Object>> THREAD_CACHE = ThreadLocal.withInitial(HashMap::new);
private static final String RMAPCACHE_KEY = "idempotent";
private static final String RMAPCACHE_KEY = "idempotent";
private static final String KEY = "key";
private static final String KEY = "key";
private static final String DELKEY = "delKey";
private static final String DELKEY = "delKey";
@Autowired
private Redisson redisson;
private final Redisson redisson;
@Autowired
private KeyResolver keyResolver;
private final KeyResolver keyResolver;
@Pointcut("@annotation(com.pig4cloud.pigx.common.idempotent.annotation.Idempotent)")
public void pointCut() {
}
@Pointcut("@annotation(com.pig4cloud.pigx.common.idempotent.annotation.Idempotent)")
public void pointCut() {
}
@Before("pointCut()")
public void beforePointCut(JoinPoint joinPoint) {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest();
@Before("pointCut()")
public void beforePointCut(JoinPoint joinPoint) {
ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder
.getRequestAttributes();
HttpServletRequest request = requestAttributes.getRequest();
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
if (!method.isAnnotationPresent(Idempotent.class)) {
return;
}
Idempotent idempotent = method.getAnnotation(Idempotent.class);
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
if (!method.isAnnotationPresent(Idempotent.class)) {
return;
}
Idempotent idempotent = method.getAnnotation(Idempotent.class);
String key;
String key;
// 若没有配置 幂等 标识编号,则使用 url + 参数列表作为区分
if (!StringUtils.hasLength(idempotent.key())) {
String url = request.getRequestURL().toString();
String argString = Arrays.asList(joinPoint.getArgs()).toString();
key = url + argString;
}
else {
// 使用jstl 规则区分
key = keyResolver.resolver(idempotent, joinPoint);
}
// 若没有配置 幂等 标识编号,则使用 url + 参数列表作为区分
if (!StringUtils.hasLength(idempotent.key())) {
String url = request.getRequestURL().toString();
String argString = Arrays.asList(joinPoint.getArgs()).toString();
key = url + argString;
} else {
// 使用jstl 规则区分
key = keyResolver.resolver(idempotent, joinPoint);
}
long expireTime = idempotent.expireTime();
String info = idempotent.info();
TimeUnit timeUnit = idempotent.timeUnit();
boolean delKey = idempotent.delKey();
long expireTime = idempotent.expireTime();
String info = idempotent.info();
TimeUnit timeUnit = idempotent.timeUnit();
boolean delKey = idempotent.delKey();
// do not need check null
RMapCache<String, Object> rMapCache = redisson.getMapCache(RMAPCACHE_KEY);
String value = LocalDateTime.now().toString().replace("T", " ");
Object v1;
if (null != rMapCache.get(key)) {
// had stored
throw new IdempotentException("[idempotent]:" + info);
}
synchronized (this) {
v1 = rMapCache.putIfAbsent(key, value, expireTime, timeUnit);
if (null != v1) {
throw new IdempotentException("[idempotent]:" + info);
}
else {
LOGGER.info("[idempotent]:has stored key={},value={},expireTime={}{},now={}", key, value, expireTime,
timeUnit, LocalDateTime.now().toString());
}
}
// do not need check null
RMapCache<String, Object> rMapCache = redisson.getMapCache(RMAPCACHE_KEY);
String value = LocalDateTime.now().toString().replace("T", " ");
Object v1;
if (null != rMapCache.get(key)) {
// had stored
throw new IdempotentException(info);
}
synchronized (this) {
v1 = rMapCache.putIfAbsent(key, value, expireTime, timeUnit);
if (null != v1) {
throw new IdempotentException(info);
} else {
LOGGER.info("[idempotent]:has stored key={},value={},expireTime={}{},now={}", key, value, expireTime,
timeUnit, LocalDateTime.now().toString());
}
}
Map<String, Object> map = THREAD_CACHE.get();
map.put(KEY, key);
map.put(DELKEY, delKey);
}
Map<String, Object> map = THREAD_CACHE.get();
map.put(KEY, key);
map.put(DELKEY, delKey);
}
@After("pointCut()")
public void afterPointCut(JoinPoint joinPoint) {
Map<String, Object> map = THREAD_CACHE.get();
if (CollectionUtils.isEmpty(map)) {
return;
}
@After("pointCut()")
public void afterPointCut(JoinPoint joinPoint) {
Map<String, Object> map = THREAD_CACHE.get();
if (CollectionUtils.isEmpty(map)) {
return;
}
RMapCache<Object, Object> mapCache = redisson.getMapCache(RMAPCACHE_KEY);
if (mapCache.size() == 0) {
return;
}
RMapCache<Object, Object> mapCache = redisson.getMapCache(RMAPCACHE_KEY);
if (mapCache.isEmpty()) {
return;
}
String key = map.get(KEY).toString();
boolean delKey = (boolean) map.get(DELKEY);
String key = map.get(KEY).toString();
boolean delKey = (boolean) map.get(DELKEY);
if (delKey) {
mapCache.fastRemove(key);
LOGGER.info("[idempotent]:has removed key={}", key);
}
THREAD_CACHE.remove();
}
if (delKey) {
mapCache.fastRemove(key);
LOGGER.info("[idempotent]:has removed key={}", key);
}
THREAD_CACHE.remove();
}
}