作者:殷天文
來源:www.jianshu.com/p/09860b74658e
在傳統的web項目中,防止重複提交,通常做法是:後端生成一個唯一的提交令牌(uuid),並存儲在服務端。頁面提交請求攜帶這個提交令牌,後端驗證並在第一次驗證後刪除該令牌,保證提交請求的唯一性。
上述的思路其實沒有問題的,但是需要前後端都稍加改動,如果在業務開發完在加這個的話,改動量未免有些大了,本節的實現方案無需前端配合,純後端處理。
思路
- 自定義註解 @NoRepeatSubmit 標記所有Controller中的提交請求
- 通過AOP 對所有標記了 @NoRepeatSubmit 的方法攔截
- 在業務方法執行前,獲取當前用戶的 token(或者JSessionId)+ 當前請求地址,作為一個唯一 KEY,去獲取 Redis 分佈式鎖(如果此時併發獲取,只有一個線程會成功獲取鎖)
- 業務方法執行後,釋放鎖
關於Redis 分佈式鎖
不瞭解的同學戳這裡 ==> Redis分佈式鎖的正確實現方式
使用Redis 是為了在負載均衡部署,如果是單機的部署的項目可以使用一個線程安全的本地Cache 替代 Redis
Code
這裡只貼出 AOP 類和測試類,完整代碼:
https://github.com/TavenYin/taven-springboot-learning/tree/master/repeat-submit-intercept
多線程測試
測試代碼如下,模擬十個請求併發同時提交
成功防止重複提交,控制檯日誌如下,可以看到十個線程的啟動時間幾乎同時發起,只有一個請求提交成功了
本節demo
https://gitee.com/yintianwen7/taven-springboot-learning/tree/master/repeat-submit-intercept
build項目之後,啟動本地redis,運行項目自動執行測試方法
參考
https://www.jianshu.com/p/09c6b05b670a
閱讀更多 Java面試 的文章