1. 程式人生 > >Struts2中防止表單重複提交的兩種方式

Struts2中防止表單重複提交的兩種方式

防止表單重複提交,這是個很重要的知識點,而且很有用。當用戶提交了一個表單,此時,位址列顯示的是處理這個表單的Action的地址,若此時重新整理,則會重新發送一次表單資料,即又進行了一次提交,若這個Action是用來處理使用者註冊的,那麼重複提交會再一次向資料庫中插入之前已經插入的資料,這顯然不是我們想要的。有兩種方法,可以防止表單重複提交,一種是用Action的重定向,一種是用Session Token(Session令牌)。

第一種方法,Action處理完使用者提交的資料後,重定向到另一個Action或是一個頁面,使使用者提交後,所停留的位置,不是當前處理資料的Action,這樣使用者再重新整理時,就不會再次執行這個Action了,就會避免表單重複提交的問題了。

第二種方法,是一種很經典的處理這個問題的機制。這種方法是在使用者要提交的表單中,加入一個<s:token>標籤,這樣,當瀏覽器第一次訪問這個帶有<s:token>標籤的頁面時,在伺服器中,解析<s:token>標籤的類(TokenTag.class),會生成一個隨機的字串(這個字串,檢視網頁的原始碼可以看到),並且傳送給客戶端的瀏覽器,同時,在伺服器中,會把這個隨機字串儲存到使用者的session物件中。當第一次提交表單時,在伺服器中,會比較客戶端和伺服器中分別儲存的這個隨機字串,因為是第一次提交,所以這兩個字串相等,然後進行正常的業務處理。第一次提交後,在伺服器中的session中儲存的這個隨機字串,會改變為其他的隨機值,注意,這是很重要的一步!

此時,位址列停留在處理使用者提交資料的Action中,客戶端中儲存的隨機字串沒有改變,若是重新整理頁面,即重複提交,伺服器再進行兩個字串的比較,會不相等,就會跳轉到name為invalid.token的結果頁面中,這樣就會防止表單重複提交了。

第一種方法的舉例,在上一篇部落格中,這裡就不再列出了,這裡主要舉例說明一下session token的機制:

  1. Login.jsp:  
  2. <s:formaction="/test/token"theme="simple">
  3.         username:<s:textfieldname="username"></s:textfield
    ><br>
  4.         password:<s:passwordname="password"></s:password><br>
  5.         <s:submitvalue="submit"></s:submit>
  6.         <s:token></s:token><!--一定要有這個標籤-->
  7.     </s:form>
  1. struts.xml:  
  2. <actionname="token"class="com.suo.actions.TokenAction">
  3.             <resultname="success">/WEB-INF/result/LoginResult.jsp</result>
  4.             <resultname="invalid.token">/WEB-INF/result/TokenFailed.jsp</result>
  5.             <!-- 若重複提交,則會跳轉到這個頁面,注意這裡result的名字,一定要是invalid.token -->
  6.             <interceptor-refname="token"></interceptor-ref>
  7.             <interceptor-refname="defaultStack"></interceptor-ref>
  8.             <!-- 這裡一定要有這兩個攔截器 -->
  9.         </action>
  1. TokenAction.java:  
  2. package com.suo.actions;  
  3. import java.util.Map;  
  4. import javax.servlet.http.HttpServletRequest;  
  5. import javax.servlet.http.HttpSession;  
  6. import org.apache.struts2.ServletActionContext;  
  7. import com.opensymphony.xwork2.ActionContext;  
  8. import com.opensymphony.xwork2.ActionSupport;  
  9. publicclass TokenAction extends ActionSupport {  
  10.     private String username;  
  11.     private String password;  
  12.     public String getUsername() {  
  13.         return username;  
  14.     }  
  15.     publicvoid setUsername(String username) {  
  16.         this.username = username;  
  17.     }  
  18.     public String getPassword() {  
  19.         return password;  
  20.     }  
  21.     publicvoid setPassword(String password) {  
  22.         this.password = password;  
  23.     }  
  24.     public String execute()  
  25.     {     
  26.         return SUCCESS;  
  27.     }  
  28. }  

結果頁面就不寫了

原博文地址:http://blog.csdn.net/hackerain/article/details/6990121

PS:

Struts2 解決表單的重複提交問題:(兩種方式:①Action的重定向②如下)
I. 在 s:form 中新增 s:token 子標籤
> 生成一個隱藏域
> 在 session 新增一個屬性值
> 隱藏域的值和 session 的屬性值是一致的. 
II. 使用 Token 或 TokenSession 攔截器. 
> 這兩個攔截器均不在預設的攔截器棧中, 所以需要手工配置一下
> 若使用 Token 攔截器, 則需要配置一個 token.valid 的 result
> 若使用 TokenSession 攔截器, 則不需要配置任何其它的 result
III. Token VS TokenSession
> 都是解決表單重複提交問題的
> 使用 token 攔截器會轉到 token.valid 這個 result
> 使用 tokenSession 攔截器則還會響應那個目標頁面, 但不會執行 tokenSession 的後續攔截器. 就像什麼都沒發生過一樣!
IV. 可以使用 s:actionerror 標籤來顯示重複提交的錯誤訊息. 
該錯誤訊息可以在國際化資原始檔中覆蓋. 該訊息可以在 struts-messages.properties 檔案中找到
struts.messages.invalid.token=The form has already been processed or no token was supplied, please try again.