首先說說重復提交是怎麼產生的,一般情況下有兩種方式: 1,頁面提交後再次刷新頁面。 2,在提交的時候多次點擊提交按鈕。 strut1.x中解決防止提交1的方法是通過重定向解決,但是方式2在網速很慢或者是用戶快速的點擊提交按鈕時,還是能夠重復提交數據。 struts2中為方式2提供了解決方案(方式1用重定向是也可以防止用戶刷新頁面而引起的重復提交),struts2通過使用令牌(token)解決此類的問題。 要使用token,首先在頁面上在你要提交的表單中加上<s:token/>,次標簽解析後會生成兩個隱藏域: [html] <span style="font-size:12px;"> <input type ="hidden" name ="struts.token.name" value ="struts.token" /> <input type ="hidden" name ="struts.token" value ="LVYMI4CX9YBDS9A0AAF9UAJL8UDX1N05 " /> </span> 在該標簽執行完成後會生成一個隨機的值(紅色部分),該值同時會加入到session中。 其次,就是在你個struts.xml中加入token攔截器。 [html] <package name="token-struts" extends="struts-default"> <interceptors> <interceptor name="token"/> <interceptor-stack name="token-default"> <interceptor-ref name=" token "/> <interceptor-ref name="defaultStack"/> </interceptor-stack> </interceptors> <default-interceptor-ref name="token-default"/> </package> 如果是用注解的話,那麼的action要這麼定義:@ParentPackage("token-struts")。 如果不是注解,可以將上面的攔截器棧加入到你的actin定義中。 這樣就完成了整個防止重復提交的任務了。 如果你想了解此攔截器是這麼工作的,你可以打開源碼看看,其中TokenHelper.validToken()最是關鍵,就是通過這個幫助類完成對令牌的判斷。 上述是可以解決重復提交的問題,但是隨之而來的又是一個麻煩。 攔截器顧名思義就是用來對請求進行攔截的,一個請求在執行前就被攔截了,默認情況下攔截器會攔截被配置下所有的請求。但是很多情況下該配置下的其他請求不需要這個攔截,比如刪除,更新操作。就完成不需要這個攔截器去攔截。攔截器又不能區分不同的請求而做出不同的操作。 這種情況就有兩種解決方案: 第一,不用token攔截器,只在你需要防止重復提交的action處理方法中加入 TokenHelper.validToken()這個判斷,如果為返回true就執行,否則跳過。 第二,用token攔截器,但是重寫此攔截器TokenInterceptor。在重寫的攔截器中判斷tokenNames,如果值為空則不做任何操作,如果有值則做攔截。 1、使用Struts2的表單標簽,其中需要增加token標簽。index.jsp表單頁面 [html] <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>防止表單重復提交</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> </head> <body> <!-- 防止表單重復提交,記得在form表單裡填上<s:token></s:token> --> <!-- action="token"、action="tokenSession" --> <s:form action="token" namespace="/test" method="post"> 姓名:<s:textfield name="name"/><s:token></s:token> <input type="submit" value="發送"/> </s:form> </body> </html> 2.PersonAction類 [java] <span style="font-size:12px;">package com.ljq.action; import java.util.ArrayList; import java.util.List; public class PersonAction { private String name; @SuppressWarnings("unchecked") //觀看控制台 //如果token生效則不會在控制台輸出name的值,而會輸出如下警告: 2011-3-14 20:45:32 com.opensymphony.xwork2.util.logging.commons.CommonsLogger //warn 警告: Form token EDZ4S96RNDN5VD8B1CQTK6FTHIJUPC66 does not match the session token null. public String execute() { List ls = new ArrayList(); ls.add(name); for (int i = 0; i < ls.size(); i++) { System.out.println(ls.get(i)); } return "success"; } public String getName() { return name; } public void setName(String name) { this.name = name; } }</span> 3.struts.xml配置文件 [html] <span style="font-size:12px;"><?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> <!-- 默認的視圖主題 --> <constant name="struts.ui.theme" value="simple" /> <!-- struts2在防止表單重復提交的攔截中有2個,分別是:token,tokenSession。tokenSession繼承token而來。 通常情況下,使用tokenSession客戶端感覺會比較友好。 --> <!-- 如果重復提交,會跳轉到error.jsp頁面 --> <package name="person" namespace="/test" extends="struts-default"> <action name="token" class="com.ljq.action.PersonAction"> <interceptor-ref name="defaultStack" /> <interceptor-ref name="token" /> <!-- 如果重復提交,跳轉到error.jsp頁面 --> <result name="invalid.token">/WEB-INF/page/error.jsp</result> <result>/WEB-INF/page/message.jsp</result> </action> <action name="tokenSession" class="com.ljq.action.PersonAction"> <interceptor-ref name="defaultStack" /> <interceptor-ref name="tokenSession" /> <!-- 如果重復提交,不會跳轉到error.jsp頁面 --> <result name="invalid.token">/WEB-INF/page/error.jsp</result> <result>/WEB-INF/page/message.jsp</result> </action> </package> </struts></span> 4.message.jsp返回成功頁面 [html] <span style="font-size:12px;"><%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>My JSP 'index.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> </head> <body> <s:property value="name"/><br/> <%=new Date() %> </body> </html></span> 5.error.jsp表單重復提交提示頁面 [html] <span style="font-size:12px;"><%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>My JSP 'error.jsp' starting page</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> 您已經提交了表單,請不要重復提交。 </body> </html></span>