防止表單重復(fù)提交,這是個(gè)很重要的知識(shí)點(diǎn),而且很有用。當(dāng)用戶提交了一個(gè)表單,此時(shí),地址欄顯示的是處理這個(gè)表單的Action的地址,若此時(shí)刷新,則會(huì)重新發(fā)送一次表單數(shù)據(jù),即又進(jìn)行了一次提交,若這個(gè)Action是用來處理用戶注冊(cè)的,那么重復(fù)提交會(huì)再一次向數(shù)據(jù)庫中插入之前已經(jīng)插入的數(shù)據(jù),這顯然不是我們想要的。有兩種方法,可以防止表單重復(fù)提交,一種是用Action的重定向,一種是用Session Token(Session令牌)。
第一種方法,Action處理完用戶提交的數(shù)據(jù)后,重定向到另一個(gè)Action或是一個(gè)頁面,使用戶提交后,所停留的位置,不是當(dāng)前處理數(shù)據(jù)的Action,這樣用戶再刷新時(shí),就不會(huì)再次執(zhí)行這個(gè)Action了,就會(huì)避免表單重復(fù)提交的問題了。
第二種方法,是一種很經(jīng)典的處理這個(gè)問題的機(jī)制。這種方法是在用戶要提交的表單中,加入一個(gè)<s:token>標(biāo)簽,這樣,當(dāng)瀏覽器第一次訪問這個(gè)帶有<s:token>標(biāo)簽的頁面時(shí),在服務(wù)器中,解析<s:token>標(biāo)簽的類(TokenTag.class),會(huì)生成一個(gè)隨機(jī)的字符串(這個(gè)字符串,查看網(wǎng)頁的源代碼可以看到),并且發(fā)送給客戶端的瀏覽器,同時(shí),在服務(wù)器中,會(huì)把這個(gè)隨機(jī)字符串保存到用戶的session對(duì)象中。當(dāng)?shù)谝淮翁峤槐韱螘r(shí),在服務(wù)器中,會(huì)比較客戶端和服務(wù)器中分別保存的這個(gè)隨機(jī)字符串,因?yàn)槭堑谝淮翁峤?,所以這兩個(gè)字符串相等,然后進(jìn)行正常的業(yè)務(wù)處理。第一次提交后,在服務(wù)器中的session中保存的這個(gè)隨機(jī)字符串,會(huì)改變?yōu)槠渌碾S機(jī)值,注意,這是很重要的一步!此時(shí),地址欄停留在處理用戶提交數(shù)據(jù)的Action中,客戶端中保存的隨機(jī)字符串沒有改變,若是刷新頁面,即重復(fù)提交,服務(wù)器再進(jìn)行兩個(gè)字符串的比較,會(huì)不相等,就會(huì)跳轉(zhuǎn)到name為invalid.token的結(jié)果頁面中,這樣就會(huì)防止表單重復(fù)提交了。
第一種方法的舉例,在上一篇博客中,這里就不再列出了,這里主要舉例說明一下session token的機(jī)制:
-
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><!--一定要有這個(gè)標(biāo)簽-->
-
</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>
-
<!-- 若重復(fù)提交,則會(huì)跳轉(zhuǎn)到這個(gè)頁面,注意這里result的名字,一定要是invalid.token -->
-
-
<interceptor-ref name="token"></interceptor-ref>
-
<interceptor-ref name="defaultStack"></interceptor-ref>
-
<!-- 這里一定要有這兩個(gè)攔截器 -->
-
</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;
-
}
-
}
結(jié)果頁面就不寫了
原博文地址:http://blog.csdn.net/hackerain/article/details/6990121
PS:
Struts2 解決表單的重復(fù)提交問題:(兩種方式:①Action的重定向②如下)
I. 在 s:form 中添加 s:token 子標(biāo)簽
> 生成一個(gè)隱藏域
> 在 session 添加一個(gè)屬性值
> 隱藏域的值和 session 的屬性值是一致的.
II. 使用 Token 或 TokenSession 攔截器.
> 這兩個(gè)攔截器均不在默認(rèn)的攔截器棧中, 所以需要手工配置一下
> 若使用 Token 攔截器, 則需要配置一個(gè) token.valid 的 result
> 若使用 TokenSession 攔截器, 則不需要配置任何其它的 result
III. Token VS TokenSession
> 都是解決表單重復(fù)提交問題的
> 使用 token 攔截器會(huì)轉(zhuǎn)到 token.valid 這個(gè) result
> 使用 tokenSession 攔截器則還會(huì)響應(yīng)那個(gè)目標(biāo)頁面, 但不會(huì)執(zhí)行 tokenSession 的后續(xù)攔截器. 就像什么都沒發(fā)生過一樣!
IV. 可以使用 s:actionerror 標(biāo)簽來顯示重復(fù)提交的錯(cuò)誤消息.
該錯(cuò)誤消息可以在國際化資源文件中覆蓋. 該消息可以在 struts-messages.properties 文件中找到
struts.messages.invalid.token=The form has already been processed or no token was supplied, please try again.
|