依赖
首先保证要有aop和redis的依赖,这边就不写了
添加注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface PreventDuplicateSubmission {
/**
* 防止重复提交格式时间(单位/秒)
* @return
*/
long expireTime() default 1;
}
添加切面
@Slf4j
@Aspect
@Component
public class PreventDuplicateSubmissionAspect {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Around("@annotation(preventDuplicateSubmission)")
public Object around(ProceedingJoinPoint joinPoint, PreventDuplicateSubmission preventDuplicateSubmission) throws Throwable {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if (attributes == null) {
throw new RuntimeException("Request attributes are not available");
}
HttpServletRequest request = attributes.getRequest();
// 获取请求的唯一标识符,这里使用请求URI + 请求人ID 可根据业务选择使用参数或者token作为key
String key = request.getRequestURI() + ":" + SecurityUtils.getUserId();
log.info("redis的key:{}", key);
// 设置缓存
// 从注解中获取过期时间
long l = preventDuplicateSubmission.expireTime();
Boolean isNewKey = redisTemplate.opsForValue().setIfAbsent(key, "1", l, TimeUnit.SECONDS);
if (isNewKey != null && isNewKey) {
try {
return joinPoint.proceed(); // 继续执行目标方法
} finally {
}
} else {
throw new RuntimeException("请勿重复提交");
}
}
}
注意
此注解如果放在工具类模块(没有启动类),那么切面实现类需要指定扫描一下
例如我这种放在common工具类中的,需要在扫描类指定一下扫描路径
使用
默认间隔时间为1秒,可自定义(为空则默认),注解放在controller下的方法上
制定间隔时间为10秒