spring boot 防止重复提交
服务器端实现方案:同一客户端在2秒内对同一URL的提交视为重复提交
- 加入maven内容
- 注解接口
- 切面拦截
- 改时间也可以在切面拦截里面改,使用的时候,在对应的Controller方法中加入注解就可以了@NoRepeatSubmit
pom.xml中,增加Maven
<!--数据重复提交解决用下面两个-->
<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>
自定义注解NoRepeatSubmit.java
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD) // 作用到方法上
@Retention(RetentionPolicy.RUNTIME) // 运行时有效
/**
*@功能描述防止重复提交标记注解
*@authorcharles
*@date2020-02-26
*/
public @interface NoRepeatSubmit {
}
NoRepeatSubmitAop切面拦截,其中多少秒的设置也在这里
import javax.servlet.http.HttpServletRequest;
import com.google.common.cache.CacheBuilder;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.google.common.cache.Cache;
import java.util.concurrent.TimeUnit;
@Aspect
@Component
/**
*@功能描述aop解析注解
*@authorcharles
*@date2020-02-26
*/
public class NoRepeatSubmitAop {
private Log logger = LogFactory.getLog(getClass());
// 最大缓存 100 个,缓存过期时间为2秒
private final Cache<String, Object> cache = CacheBuilder.newBuilder()
.maximumSize(100)
.expireAfterWrite(2, TimeUnit.SECONDS)
.build();
@Around("execution(* com.example..*Controller.*(..)) && @annotation(nrs)")
public Object arround(ProceedingJoinPoint pjp, NoRepeatSubmit nrs) {
try {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
String sessionId = RequestContextHolder.getRequestAttributes().getSessionId();
HttpServletRequest request = attributes.getRequest();
String key = sessionId + "-" + request.getServletPath();
// 如果缓存中有这个url视为重复提交
if (cache.getIfPresent(key) == null) {
Object o = pjp.proceed();
cache.put(key, 0);
return o;
} else {
logger.error("重复提交");
// if(true) {
// throw new Exception("模拟未知异常!");
// }
return "重复提交了";// 这里,可以改成自己程序中统一的返回格式内容
}
} catch (Throwable e) {
e.printStackTrace();
logger.error("重复提交时出现其他的未知异常!");
// 这里,可以改成自己程序中统一的返回格式内容
return "{\"code\":-1,\"message\":\"重复提交时出现其他的未知异常!\"}";
}
}
}
测试使用
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class TestController {
@RequestMapping("/test")
@NoRepeatSubmit
public String test() {
System.out.println(123);
return ("测试返回");
}
}