1.什么是重復提交呢
? 在Web開發中,重復提交(也稱為雙重提交或重復表單提交)是指用戶在沒有明確意圖的情況下,多次提交同一表單的情況。這可能是由于用戶多次點擊提交按鈕、表單提交過程中的網絡延遲導致用戶重復點擊、或者由于瀏覽器的自動重試機制(如在網絡中斷后恢復連接時)等原因造成的。
? 這種情況可能造成數據庫插入多條數據等等
2.用一個小例子實現防止重復提交
2.1?首先自定義一個注解,用來給方法設置多長時間內再次調用相同的數據,屬于重復提交
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface ExpirationTime {// 可以定義一些屬性,比如超時時間等long timeout() default 60; // 默認60秒 }
2.2 通過AOP在執行方法前做檢查,存入到redis中,通過給redis中設置過期時間,實現防止重復提交功能
@Component @Aspect public class RepeatSubmitAspect {@Autowiredprivate RedisTemplate redisTemplate;@Pointcut("@annotation(com.qcby.submitageain.annotationaop.ExpirationTime)")public void repeatSubmit() {}@Around("repeatSubmit()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();HttpServletRequest request = attributes.getRequest();StringBuffer requestURL = request.getRequestURL();// 如果需要包括查詢字符串,可以添加String queryString = request.getQueryString();if (queryString != null) {requestURL.append("?").append(queryString);}String requestURL1 = requestURL.toString();Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();// 獲取防重復提交注解ExpirationTime annotation = method.getAnnotation(ExpirationTime.class);//設置初始值為0,表示如果該沒有這個注解,就設置過期時間為0,也就是不存入redis中long timeout=0;if(annotation!=null){timeout = annotation.timeout();}if (!redisTemplate.hasKey(requestURL1)||this.redisTemplate.opsForValue().get(requestURL1)==null) {this.redisTemplate.opsForValue().set(requestURL1, true, timeout, TimeUnit.SECONDS);try {//正常執行方法并返回return joinPoint.proceed();} catch (Throwable throwable) {throw new Throwable(throwable);}} else {// 拋出異常System.out.println("請勿重復提交");return null;}} }
2.3 此時就可以編寫controller層來測試代碼是否成功啦~
@Controller public class TestController {@RequestMapping("/a2")@ExpirationTime(timeout = 5)@ResponseBodypublic void test(){System.out.println("提交成功");}@RequestMapping("/a1")@ResponseBodypublic void test1(){System.out.println("提交成功1");} }
2.4 此刻一個簡單的防止重復提交的一個小程序就完成啦~