mirror of
http://git.pig4cloud.com/pig/pigx.git
synced 2026-11-09 04:49:02 +08:00
refactor(common-idempotent): 幂等插件重构@Idempotent默认值
默认执行完后删除key 修改默认错误信息格式
This commit is contained in:
1 parent
6bd7bd33a9
commit
c75a491bf5
3 files changed
+100
-107
No files matched your search
+23
-17
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -39,6 +39,6 @@ public @interface Idempotent {
|
||||
* 是否在业务完成后删除key true:删除 false:不删除
|
||||
* @return boolean
|
||||
*/
|
||||
boolean delKey() default false;
|
||||
boolean delKey() default true;
|
||||
|
||||
}
|
||||
+76
-89
@@ -1,10 +1,9 @@
|
||||
package com.pig4cloud.pigx.common.idempotent.aspect;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.pig4cloud.pigx.common.core.util.KeyStrResolver;
|
||||
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 lombok.RequiredArgsConstructor;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.annotation.After;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
@@ -15,7 +14,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;
|
||||
@@ -27,7 +25,6 @@ import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
@@ -36,110 +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;
|
||||
|
||||
@Autowired
|
||||
private Optional<KeyStrResolver> keyStrResolverOptional;
|
||||
@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();
|
||||
|
||||
if (keyStrResolverOptional.isPresent()) {
|
||||
key = keyStrResolverOptional.get().extract(key, StrUtil.COLON);
|
||||
}
|
||||
// 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());
|
||||
}
|
||||
}
|
||||
|
||||
long expireTime = idempotent.expireTime();
|
||||
String info = idempotent.info();
|
||||
TimeUnit timeUnit = idempotent.timeUnit();
|
||||
boolean delKey = idempotent.delKey();
|
||||
Map<String, Object> map = THREAD_CACHE.get();
|
||||
map.put(KEY, key);
|
||||
map.put(DELKEY, 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());
|
||||
}
|
||||
}
|
||||
@After("pointCut()")
|
||||
public void afterPointCut(JoinPoint joinPoint) {
|
||||
Map<String, Object> map = THREAD_CACHE.get();
|
||||
if (CollectionUtils.isEmpty(map)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, Object> map = THREAD_CACHE.get();
|
||||
map.put(KEY, key);
|
||||
map.put(DELKEY, delKey);
|
||||
}
|
||||
RMapCache<Object, Object> mapCache = redisson.getMapCache(RMAPCACHE_KEY);
|
||||
if (mapCache.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
@After("pointCut()")
|
||||
public void afterPointCut(JoinPoint joinPoint) {
|
||||
Map<String, Object> map = THREAD_CACHE.get();
|
||||
if (CollectionUtils.isEmpty(map)) {
|
||||
return;
|
||||
}
|
||||
String key = map.get(KEY).toString();
|
||||
boolean delKey = (boolean) map.get(DELKEY);
|
||||
|
||||
RMapCache<Object, Object> mapCache = redisson.getMapCache(RMAPCACHE_KEY);
|
||||
if (mapCache.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user