整体思路简单介绍:
- 自定义注解
- 设置切面,扫描 被 “自定义注解” 标记的方法,走切面逻辑
- 切面中用redis记录数据
- Key:【(类名+方法名)转为hash码 + ip + 常量】
- Value:关联key,并设置超时时间
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AvoidRepeatableCommit {
long timeout() default 1000;
}
@Aspect
@Component
@Slf4j
public class AvoidRepeatableCommitAspect {
@Autowired
private RedisUtil redisUtil;
@Around("@annotation(com.uatha.admin.annotion.AvoidRepeatableCommit.AvoidRepeatableCommit)")
public Object around(ProceedingJoinPoint point) throws Throwable {
HttpServletRequest request = RequestHolder.getRequest();
String ip = IpUtils.getIpAddr(request);
MethodSignature signature = (MethodSignature) point.getSignature();
Method method = signature.getMethod();
String className = method.getDeclaringClass().getName();
String name = method.getName();
String ipKey = String.format("%s#%s", className, name);
int hashCode = Math.abs(ipKey.hashCode());
String key = String.format("%s:%s_%d", RedisConf.AVOID_REPEATABLE_COMMIT, ip, hashCode);
log.info("ipKey={},hashCode={},key={}", ipKey, hashCode, key);
AvoidRepeatableCommit avoidRepeatableCommit = method.getAnnotation(AvoidRepeatableCommit.class);
long timeout = avoidRepeatableCommit.timeout();
String value = redisUtil.get(key);
if (StringUtils.isNotBlank(value)) {
log.info("请勿重复提交表单");
return ResultUtil.result(SysConf.ERROR, "请勿重复提交表单");
}
redisUtil.setEx(key, StringUtils.getUUID(), timeout, TimeUnit.MILLISECONDS);
Object object = point.proceed();
return object;
}
}