用戶重複提交表單在某些場合將會形成很是嚴重的後果。例如,在使用信用卡進行在線支付的時候,若是服務器的響應速度太慢,用戶有可能會屢次點擊提交按鈕,而這可能致使那張信用卡上的金額被消費了屢次。所以,重複提交表單會對你的系統帶來邏輯影響,必須採起一些措施防止這類狀況的發生。apache
用戶重複提交同一個HTML表單的緣由有: 1、快速屢次點擊了提交按鈕;2、提交表單後按下瀏覽器的刷新按鈕。瀏覽器
設置Struts 2的預防表單重複提交的功能 服務器
Struts 2已經內置了可以防止用戶重複提交同一個HTML表單的功能。它的工做原理:讓服務器生成一個惟一標記,並在服務器和表單裏各保存一份這個標記的副本。此後,在用戶提交表單的時候,表單裏的標記將隨着其餘請求參數一塊兒發送到服務器,服務器將對他收到的標記和它留存的標記進行比較。若是二者匹配,此次提交的表單被認爲是有效的,服務器將對之作出必要的處理並從新設置一個新標記。隨後,提交相同的表單就會失敗,由於服務器上的標記已經重置。 jsp
Struts 2標籤中的token標籤,能夠用來生成一個獨一無二的標記。這個標記必須嵌套在form標籤中使用,它會在表單裏插入一個隱藏字段並把標記保存到HttpSession對象裏。toke標籤必須與Token或Token Session攔截器配合使用,兩個攔截器都能對token標籤進行處理。Token攔截器遇到重複提交表單的狀況,會返回一個"invalid.token"結果並加上一個動做級別的錯誤。Token Session攔截器擴展了Token攔截器並提供了一種更復雜的服務,它採起的作法與Token攔截器不一樣,它只是阻斷了後續的提交,這樣用戶不提交多少次,就好像只是提交了一次。 ide
示例:使用Token攔截器預防表單重複提交測試
1. 配置struts.xml文件,聲明動做this
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <package name="avoidPackage" extends="struts-default"> <action name="avoid" class="struts2.action.AvoidAction"> <interceptor-ref name="token"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> <result name="invalid.token">/error.jsp</result> <result name="input">/input.jsp</result> <result name="success">/output.jsp</result> </action> </package> </struts>
此時,須要在動做的聲明中,爲動做添加token攔截器,由於token攔截器不在defaultStack攔截器棧中,注意,須要將攔截器放在攔截器棧的第一位,這是由於判斷表單是否被重複提交的邏輯應該在表單處理前。spa
2. 建立動做類orm
public class AvoidAction extends ActionSupport { private static final long serialVersionUID = 2676453800249807631L; private String username; private Date birthday; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } @Override public String execute() { try { Thread.sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); } return SUCCESS; } }
這個動做邏輯處理爲掛起4秒鐘,讓咱們有機會屢次點擊提交按鈕,測試效果。xml
3. 建立頁面:
input.jsp
<s:form action="avoid"> <s:token></s:token> <s:textfield name="username" label="Enter your name"></s:textfield> <s:textfield name="birthday" label="Enter your birthday"></s:textfield> <s:submit value="submit"></s:submit> </s:form>
要使用Struts 2的防止表單重複提交功能,須要在form標籤中使用token標籤,他會產生一個惟一的標識符,與其餘參數一塊兒提交到服務器,服務器會根據token標籤所產生的標識符判斷表單是否爲重複提交的表單,這個功能是由Token攔截器完成的。
error.jsp
<body> do not duplicate submissions form! </body>
當表單重複提交,Token攔截器會返回一個"invalid.token"結果,結果將頁面轉到這個頁面,提示用戶錯誤信息。
output.jsp
<body> Your Name : <s:property value="username"/> <br /> Your Birthday : <s:property value="birthday"/> </body>
若沒有重複提交表單,那麼就顯示正確的頁面。
4. 測試
在瀏覽器中輸入:http://localhost:8081/AvoidDuplicateSubmissions/input.jsp,獲得以下界面
連續屢次點擊"submit"按鈕,查看效果
能夠看到,token攔截器的設置生效了,他阻止了表單的重複提交,並給出了錯誤提示
此次咱們只點擊一次提交(請從新輸入URL,或後退到輸入頁面後刷新一下,這是由於token的標示在提交一次後已被修改,不刷新標示符是不可能與服務器存留的標示符一致的)
能夠看到,表單被正確的處理了。
處理表單重複提交的另外一個攔截器是 tokenSession,使用該攔截器與使用token攔截器並無什麼差別只須要,引用該攔截器,其餘與token攔截器徹底一致
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <package name="avoidPackage" extends="struts-default"> <action name="avoid" class="struts2.action.AvoidAction"> <interceptor-ref name="tokenSession"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> <result name="invalid.token">/error.jsp</result> <result name="input">/input.jsp</result> <result name="success">/output.jsp</result> </action> </package> </struts>