springboot和vue使用时网络卡导致请求并发提交
数据请求做了去重处理,但是无法处理重复并发请求
实现代码
我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客:
<!--处理表单重复提交-->
<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>
package com.shiniukeji.myatatinterface;
/**
* Create With IDEA
*
* @author:cherry
* @date:2019/8/9
* @time:18:00
*/
/**
* 自定义一个注解,给需要防止重复提交的方法加上该注解
*/
public @interface RepeatSubmit {
}
package com.shiniukeji.myatatinterface;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.shiniukeji.model.ErrCode;
import com.shiniukeji.model.ResponseResult;
import com.shiniukeji.model.User;
import com.shiniukeji.web.UserController;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.Configuration;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;
/**
* Create With IDEA
*
* @author:cherry
* @date:2019/8/9
* @time:18:00
*/
@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.shiniukeji.myatatinterface.RepeatSubmit)")
public void pointCut() {
}
@Around("pointCut()")
public Object interceptor(ProceedingJoinPoint pjp) {
User user = (User) SecurityUtils.getSubject().getSession().getAttribute(UserController.USER_SESSION_KEY);
if (user == null) {
return new ResponseResult(ErrCode.ERR_CODE_FAILED,ErrCode.RESULT_FAILED,ErrCode.ERR_TOKEN_OUTTIME);
}
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 {
ResponseResult resultResponse = new ResponseResult();
resultResponse.setResult(null);
resultResponse.setMessage("请勿重复请求");
resultResponse.setCode(ErrCode.ERR_CODE_FAILED);
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();
}
}