天天看點

How to avoid repeated submission of forms

使用者在表單中填寫完資訊,點選“送出”按鈕後,可能會因為沒有看到成功資訊而再次點選“送出按鈕”,進而導緻在服務端接收到兩條同樣的資訊,如果這個信用是要儲存到資料跌,那麼就會出再現兩條重複的資訊,或者出現資料庫操作異常(如果字段設定了唯一性限制)。在實際應用中,由于使用者沒有及時看到響應資訊而導緻的重複送出時有發生,響應不及時有可能是因為在這個時段伺服器的負載比較大,或者服務上的某個應用占用了較多資源,導緻對使用者送出資料處理時間過長,又或者這個處理本身就是比較耗時的操作。

有時即使響應及時,也可能出現表單重複送出的情況。伺服器端的程式在處理完使用者送出的資訊後,調用RequestDispatcher.forward()方法将使用者請求導向到成功頁面,使用者看到成功資訊後,點選了“重新整理”按鈕,此時浏覽器将再次送出使用者先前輸入的資料。這是因為調用RequestDispatcher.forward()傳回的成功頁面,浏覽器所保留的URL是先前表單送出的URL,如果是采用HttpServletResponse.sendRedirect()方法将用戶端重定向到成功頁面,就不會出現重複送出的問題了。

避免表單重複送出可以在用戶端通過JavaScript腳本實作,也可以在伺服器端編寫代碼實作。

在用戶端通過JavaScript實作的時候,可以借助遮罩功能阻止使用者在表單成功傳回前重複送出資料。

在服務端實作的話,方法比較多,不過使用最多的還是基于會話令牌來實作。其基本原理如下:

(1)使用者通路包含表單的頁面,服務端在這次會話中,建立一個Session對象,并産生一個令牌,将這個令牌值作為隐藏域的值,随表單一起發送到用戶端,同時将令牌值儲存到Session中。

(2)使用者送出頁面,服務端首先決斷文法參數中的令牌值和Session中儲存的令牌值是否相同,如果相同,則清除Session中的令牌值,然後執行資料處理操作,不相同,則提示使用者已經送出過表單了。同時産生一個新的令牌值,儲存到Session中當使用者重新通路資料送出頁面時,将新産生的令牌的值作為隐藏輸入域的值。

參考文獻
  • 《Struts2深入詳解》/ 孫鑫著;北京:電子工業出版社,2008.7;ISBN 987-7-121-06812-6

繼續閱讀