package com.platform.aspect.request;
import java.lang.annotation.*;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CheckRepeatCommit {
String channel() default "APP";
int expireTime() default 3;
}
package com.platform.aspect.request;
import cn.hutool.core.util.StrUtil;
import com.platform.common.exception.BusinessException;
import com.platform.design.strategy.snatchtreasure.participation.params.YwzcParticipationGoodsSnatchTreasureParameter;
import com.platform.design.strategy.snatchtreasure.participation.params.YwzcParticipationSnatchTreasureParameter;
import com.platform.design.strategy.snatchtreasure.participation.params.YwzcParticipationTokenSnatchTreasureParameter;
import com.platform.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;
@Component
@Aspect
@Slf4j
public class CheckRepeatCommitAspect {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private JwtUtils jwtUtils;
@Pointcut("@annotation(com.platform.aspect.request.CheckRepeatCommit)")
private void checkRepeatCommit() {
}
@Around("checkRepeatCommit()")
public Object checkRepeatCommit(ProceedingJoinPoint joinPoint) throws Throwable {
String methodName = joinPoint.getSignature().getName();
Object target = joinPoint.getTarget();
//得到拦截的方法
Method method = getMethodByClassAndName(target.getClass(), methodName);
log.info("验证是否重复提交:" + "调用方法:" + method);
//请求的方法名
String className = joinPoint.getTarget().getClass().getName();
String channel = "";
String bizKey = method.getName();
int expireTime = 0;
// 获取异常抛出接口的request对象
RequestAttributes ra = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes sra = (ServletRequestAttributes) ra;
assert sra != null;
HttpServletRequest request = sra.getRequest();
// YwzcParticipationSnatchTreasureParameter params = (YwzcParticipationSnatchTreasureParameter) getMethodOverParamByName(joinPoint, "params");
//
// String userNo = params.getUserId();
String token = request.getHeader(jwtUtils.getHeader());
String userNo = null;
if (StringUtils.isBlank(token)) {
userNo = jwtUtils.getClaimByToken(token).getSubject();
}
String key;
// 获取当前请求方法的注解,根据注解配置获取参数
CheckRepeatCommit checkRepeatCommit = method.getAnnotation(CheckRepeatCommit.class);
if (checkRepeatCommit != null) {
//注解上的描述
channel = checkRepeatCommit.channel();
expireTime = checkRepeatCommit.expireTime();
key = getRepeatCommitLock(channel, className, bizKey, userNo, expireTime);
if (StringUtils.isBlank(key)) {
throw new BusinessException("操作太频繁了!!!", 500);
}
}
return joinPoint.proceed();
}
/**
* 获取指定参数
*
* @param joinPoint
* @param paramName
* @return
*/
private static Object getMethodOverParamByName(JoinPoint joinPoint, String paramName) {
// 获取目标方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
// 获取目标方法的入参值列表
Object[] args = joinPoint.getArgs();
// 获取目标方法的入参名列表
String[] parameterNames = new DefaultParameterNameDiscoverer().getParameterNames(method);
// 根据入参名匹配到对应的入参值
for (int i = 0; i < parameterNames.length; i++) if (parameterNames[i].equals(paramName)) return args[i];
return null;
}
/**
* 根据类和方法名得到方法
*/
public Method getMethodByClassAndName(Class c, String methodName) {
Method[] methods = c.getDeclaredMethods();
for (Method method : methods) {
if (method.getName().equals(methodName)) {
return method;
}
}
return null;
}
public String getRepeatCommitLock(String channel, String module, String bizKey, String userNo, int expireTime) {
if (StringUtils.isEmpty(module) || StringUtils.isEmpty(bizKey)) {
throw new BusinessException("getRepeatCommitLock{} 参数不能为空!");
}
String redisKey = channel + StrUtil.COLON + module + StrUtil.COLON + bizKey + StrUtil.COLON + userNo;
long count = redisTemplate.opsForValue().increment(redisKey, 1);
if (count == 1) {
if (expireTime == 0) {
expireTime = 60;
}
redisTemplate.expire(redisKey, expireTime, TimeUnit.SECONDS);
return redisKey;
} else {
return null;
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151