通过redis的有效期和切面来配合处理
/**
* 标记为防抖处理接口(注意需要先满足登录)
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Debounce {
/**
* 定义防抖key
* @return
*/
String key() default "";
/**
* 防抖时间,默认1s
* @return
*/
long ms() default 1000;
}
说明:上面注解用于需要防抖的接口方法上。注解实用和写法更多可参考:
@Slf4j
@Aspect
@Component
public class DebounceAspect {
@Around("@annotation(com.xx.annotation.Debounce)")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
Signature signature = joinPoint.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method targetMethod = methodSignature.getMethod();
Long userId = Global.getUserId();
/**
* 防抖
*/
Debounce debounce = targetMethod.getAnnotation(Debounce.class);
String clazzName = targetMethod.getDeclaringClass().getSimpleName();
String name = clazzName.replace(".","_")+"_"+targetMethod.getName();
String key = StrUtil.isEmpty(debounce.key())? name+":"+userId: name+":"+userId+":"+debounce.key();
String cacheKey = RedisKeyGenerator.debounceKey(key);
boolean exists = RedisTemplateHelper.exists(cacheKey);
if (exists){
throw new BusinessException(8899,"操作频繁,请稍后再试:"+name);
}
RedisTemplateHelper.setMs(cacheKey,cacheKey,debounce.ms());
return joinPoint.proceed();
}
}
上面处理中通过Global.getUserId()
获取了当前登录用户的id,你根据自己实际获取登录用户ID方式获取即可。
key的生成,key核心部分就是 获取的 className (类名) + 方法名 + 用户id组成
key生成后存放到redis里面并设定过期时间,过期时间来源于注解@Debounce
的配置
判断逻辑:每次组合key,然后去redis判断是否存在,存在则表示操作频繁,这里就添加了一个异常。不存在则正常访问。
以上逻辑编写好以后,可以通过接口文档频繁点击测试:
http://blog.xqlee.com/article/240309154544389.html