@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface PreventDuplicateSubmit {
/** 请求间隔时间,单位秒,该时间范围内的请求为重复请求 */
int intervalTime() default 1;
/** 返回的提示信息 */
String msg() default "请不要频繁重复请求!";
}
@Component
public class PreventDuplicateSubmitCache {
/**
* 重复提交缓存
*/
public static final Map<Date, String> REPEAT_REQUEST = new HashMap<>();
/**
* 向缓存中存入数据
*
* @param key
* @param value
*/
public void add(Date key, String value) {
REPEAT_REQUEST.put(key, value);
}
}
@Component
@Aspect
@Order(100)
public class PreventDuplicateSubmitHandler {
@Resource
private PreventDuplicateSubmitCache requestCache;
// 定义注解类型的切点
@Pointcut("@annotation(fish.api.server.security.PreventDuplicateSubmit)")
public void arrPointcut() {
}
// 实现过滤重复请求功能
@Around("arrPointcut()")
public Object arrBusiness(ProceedingJoinPoint joinPoint) {
// 获取 map value,由 session id 和 请求URI 构成
ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
HttpServletRequest request = sra.getRequest();
String value = request.getSession().getId() + "_" + request.getRequestURI();
// 获取方法的 AvoidRepeatRequest 注解
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
PreventDuplicateSubmit arr = method.getAnnotation(PreventDuplicateSubmit.class);
// 判断是否是重复的请求
Date now = new Date();
requestCache.add(now, value);
List<Date> list = new ArrayList<>();
Map<Date, String> map = PreventDuplicateSubmitCache.REPEAT_REQUEST;
for (Map.Entry<Date, String> entry : map.entrySet()) {
if (entry.getKey().equals(now) && entry.getValue().equals(value)) {
continue;
}
list.add(entry.getKey());
//传入的时间和原本时间的差值(秒)
int difference = (int) (now.getTime() - entry.getKey().getTime()) / 1000;
//如果时间差小于设定值为重复提交
if (difference < arr.intervalTime()) {
return new Result<>(902, arr.msg());
}
}
//删除之前的数据
if (CollUtil.isNotEmpty(list)) {
list.forEach(map::remove);
}
try {
// 非重复请求,执行业务代码
return joinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
return ("error");
}
}
}
应用