/**
* 自定义一个注解,给需要防止重复提交的方法加上该注解
*/
public @interface RepeatSubmit {
}复制代码
使用spring的aop,对注解进行切面,通过guava的缓存来记录提交和设置过期时间
@Aspect
@Configuration
public class SubmitAspect {
private final Cache<String, Object> CACHES = CacheBuilder.newBuilder()
// 最大缓存 100 个
.maximumSize(100)
// 设置缓存过期时间为S
.expireAfterWrite(3, TimeUnit.SECONDS)
.build();
@Pointcut("@annotation(com.bccah.modweb.home.annotation.RepeatSubmit)")
public void pointCut() {
}
@Around("pointCut()")
public Object interceptor(ProceedingJoinPoint pjp) {
WebAccountInfoDO user = UserShiroUtils.getUser();
if (user == null) {
return ResultTool.fail(ResultTool.HttpResponseCode.NOT_LOGIN);
}
MethodSignature signature = (MethodSignature) pjp.getSignature();
Method method = signature.getMethod();
RepeatSubmit form = method.getAnnotation(RepeatSubmit.class);
String key = getCacheKey(user.getId(), method, pjp.getArgs());
if (!StringUtils.isEmpty(key)) {
if (CACHES.getIfPresent(key) == null) {
// 如果是第一次请求,就将key存入缓存中
CACHES.put(key, key);
} else {
ResultEntity resultResponse = new ResultEntity();
resultResponse.setData(null);
resultResponse.setMsg("请勿重复请求");
resultResponse.setCode(405);
return resultResponse;
}
}
try {
return pjp.proceed();
} catch (Throwable throwable) {
throw new RuntimeException("服务器异常");
}
}
/**
* 加上用户的唯一标识
*/
private String getCacheKey(String uid, Method method, Object[] args) {
return uid + "/" + method.getName();
}
}复制代码
需要添加的注解有
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>27.1-jre</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>复制代码