通常是唯一标示+redis的setnx命令加上时间间隔,配合spring环绕通知实现的,还需要加日志等收集错误信息等,这里就不介绍了
代码逻辑:唯一表示采用:ip+方法里面的一堆参数+个人信息,主要逻辑就是下面这样,分布式锁也同理可以通过这个方法实现
/**
* 幂等性接口处理的环绕通知
* 核心需要找到一些唯一的标记
* 1.拿到请求的ip
* 2.拿到请求的方法名称
* 3.拿到参数值
* 4.拿到当前用户的身份 id
* 5.组合成一个唯一的标记
* 6.通过redis的setnx方法(set if not exist)
* 7.拦截还是执行目标方法
*
* @param joinPoint
* @return
*/
@Around(value = "@annotation(com.powernode.anno.Idempotence)")
public Object IdempotenceAround(ProceedingJoinPoint joinPoint) {
Object result = null;
//获取ip
String ip = WebUtil.getIp();
//方法
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
Method method = signature.getMethod();
String methodName = method.getName();
//类
Class<?> aClass = method.getDeclaringClass();
String typeName = aClass.getName();
//参数
Object[] args = joinPoint.getArgs();
String argsStr = JSON.toJSONString(args);
//当前身份标示
Integer userId = 1;
//唯一标示
String key = ip + "-" + typeName + "-" + methodName + "-" + argsStr + "-" + userId;
//这里后面啊的表示只能一秒请求一次
Boolean flag = redisTemplate.opsForValue().setIfAbsent("Idempotence:" + key, "", Duration.ofSeconds(1));
if (flag) {
try {
result = joinPoint.proceed(args);
return result;
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}
//到这里说明这个吊毛1s请求了很多次
System.out.println("抛出异常");
return 0;
}
}