現象
Servlet 故意 Thread.sleep(2000),用戶連點提交按鈕,控制台輸出多次「***************」,Chrome Network 面板顯示前幾個請求狀態為 canceled,最後一個正常返回。
原因解析
- 瀏覽器發出請求 1 → 等待響應。
- 用戶未耐心等待,再次點擊提交 → 瀏覽器發出請求 2,**同時取消請求 1** (狀態 canceled)。
- 以此類推,只有最後一個請求完成響應,前序請求均被用戶操作隱式取消。
- 服務端仍處理所有請求(除非有防重機制),故控制台打印多次。
canceled 含義
請求被客戶端主動取消**,非服務端錯誤。常見于:用戶跳轉頁面、關閉標簽、重複提交表單時瀏覽器取消前序請求。
防重複提交最佳實踐
- 前端禁用按鈕:
onclick="this.disabled=true;this.form.submit();"。
- Token 機制:Session 存隨機 Token,表單隱藏域攜帶,提交驗證並刪除 Token。
- Post-Redirect-Get (PRG):處理完 POST 重定向到 GET 頁面,刷新不重複提交。
- 服務端冪性檢查:業務主鍵唯一約束、Redis 分布式鎖。
總結
canceled 只是瀏覽器行為表現,**服務端必須假設所有請求都會被執行**,做好冪性與防重設計。