防止表單重複提交,這是個很重要的知識點,而且很有用。當用戶提交了一個表單,此時,地址欄顯示的是處理這個表單的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的機制:
- Login.jsp:
- <s:form action="/test/token" theme="simple">
- username:<s:textfield name="username"></s:textfield><br>
- password:<s:password name="password"></s:password><br>
- <s:submit value="submit"></s:submit>
- <s:token></s:token><!--一定要有這個標籤-->
- </s:form>
- struts.xml:
- <action name="token" class="com.suo.actions.TokenAction">
- <result name="success">/WEB-INF/result/LoginResult.jsp</result>
- <result name="invalid.token">/WEB-INF/result/TokenFailed.jsp</result>
- <!-- 若重複提交,則會跳轉到這個頁面,注意這裏result的名字,一定要是invalid.token -->
- <interceptor-ref name="token"></interceptor-ref>
- <interceptor-ref name="defaultStack"></interceptor-ref>
- <!-- 這裏一定要有這兩個攔截器 -->
- </action>
- TokenAction.java:
- package com.suo.actions;
- import java.util.Map;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpSession;
- import org.apache.struts2.ServletActionContext;
- import com.opensymphony.xwork2.ActionContext;
- import com.opensymphony.xwork2.ActionSupport;
- public class TokenAction extends ActionSupport {
- private String username;
- private String password;
- public String getUsername() {
- return username;
- }
- public void setUsername(String username) {
- this.username = username;
- }
- public String getPassword() {
- return password;
- }
- public void setPassword(String password) {
- this.password = password;
- }
- public String execute()
- {
- return SUCCESS;
- }
- }
結果頁面就不寫了
原博文地址: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.