當用戶填寫完表單后,在提交過一次后,若用戶做如下操作比如再次點擊提交、刷新頁面、提交頁面呈現后點擊后退按鈕,都會導致表單重復提交。如果信息需要存儲到后台數據庫中,重復提交就會再次向數據庫中插入用戶信息,顯然這樣是不對的。解決方式有兩種
(一)Session Token機制
當用戶首次訪問包含表單的頁面時,此時服務器會做三件事
1)創建一個session對象,
2)通過解析<s:token>標簽(編程時此標簽在要加入表單頁面中)會產生一個隨機數(可以將其稱為盾牌,注意這個不是session ID)保存在session中
3)服務器把產生的隨機數發送給客戶端
當用戶向服務器提交表單的時候,此時服務器會做
1)判斷從客戶端發送過來的請求參數中的隨機數和保存在session對象中隨機數是否相等,如果相等,則認為是第一次提交。
2)若是第一次提交,服務器會把原來保存在session的隨機數改變成其他的隨機數。當時發送給客戶端的隨機數不變。
3)因為在第一次提交表單后,服務器端地隨機數和客戶端的不一樣了,所以當重復提交的時候,服務器看到客戶端的隨機數和自己的不一樣了就可以判斷這是在重復提交了。
代碼實現:
1、表單頁面,注意:在使用session token時,必須用struts2表標簽庫
<%@taglib prefix="s" uri="/struts-tags" %>
register1.jsp頁面
<s:form action="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> <!--服務器通過token標簽 來產生盾牌隨機數--> </s:form>
struts.xml
<action name="token" class="com.struts2.TokenAction"> <result name="success">/success.jsp</result> <result name="invalid.token">/invalid.jsp</result> <interceptor-ref name="token"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </action>
TokenAction
package com.struts2; 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; } @Override public String execute() throws Exception { return SUCCESS; } }
首次提交對應的success.jsp結果頁面
<body> 注冊成功! </body>
重復提交對應的invalid.jsp結果頁面
1、在含有form表單的頁面注意使用struts2表標簽庫
2、在含有form表單的頁面加入<s:token></s:token> 標簽
3、在struts.xml頁面中配置:
<result name=”token.invalid”>/invalid.jsp</rssult> <interceptor-ref name="token"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref>