在傳統的web項目中,防止重復提交,通常做法是:后端生成一個唯一的提交令牌(uuid),並存儲在服務端。頁面提交請求攜帶這個提交令牌,后端驗證並在第一次驗證后刪除該令牌,保證提交請求的唯一性。
上述的思路其實沒有問題的,但是需要前后端都稍加改動,如果在業務開發完在加這個的話,改動量未免有些大了,本節的實現方案無需前端配合,純后端處理。
思路
1、自定義注解 @NoRepeatSubmit 標記所有Controller中的提交請求
2、通過AOP 對所有標記了 @NoRepeatSubmit 的方法攔截
3、在業務方法執行前,獲取當前用戶的 token(或者JSessionId)+ 當前請求地址,作為一個唯一 KEY,去獲取 Redis 分布式鎖(如果此時並發獲取,只有一個線程會成功獲取鎖)
4、業務方法執行后,釋放鎖
這里只貼出 AOP 類和測試類

多線程測試
測試代碼如下,模擬十個請求並發同時提交

成功防止重復提交,控制台日志如下,可以看到十個線程的啟動時間幾乎同時發起,只有一個請求提交成功了
