在webWork中有Token標簽,可以直接搞定重復提交的問題,但在Struts2.0以下的版本,傳統的做法只有通過提供的Token編程來搞定,代碼雖然不多但是,這樣的細節涉及了兩個Action,對于頁面的跳轉控制來說是一個額外的負擔,必須處處小心,本文闡述了如何通過Filter通過配置來避免struts的Form重復提交問題。
核心代碼如下:
package?com.yapulan.util.filter;?

import?java.io.IOException;?
import?java.util.HashMap;?
import?java.util.Iterator;?
import?java.util.List;?

import?javax.servlet.Filter;?
import?javax.servlet.RequestDispatcher;?
import?javax.servlet.ServletException;?
import?javax.servlet.FilterConfig;?
import?javax.servlet.http.HttpServletRequest;?
import?javax.servlet.http.HttpServletResponse;?
import?javax.servlet.FilterChain;?
import?javax.servlet.ServletRequest;?
import?javax.servlet.ServletResponse;?

import?org.apache.log4j.Logger;?
import?org.apache.struts.action.Action;?
import?org.apache.struts.action.ActionForm;?
import?org.apache.struts.action.ActionForward;?
import?org.apache.struts.action.ActionMapping;?
import?org.dom4j.Document;?
import?org.dom4j.Element;?
import?org.dom4j.io.SAXReader;?


/**?*//**?
*?重復提交令牌自動加載器?功能:讀取過濾器中設置的信息,讀入令牌設置組?
*/?


public?class?TokenFilter?implements?Filter?
{?

private?String?TokenConfig?=?"TokenConfig.xml";?
private?HashMap?TokenMap?=?null;?
private?HashMap?ErrorMap?=?null;?
protected?FilterConfig?filterConfig;?
static?Logger?logger?=?Logger.getLogger(TokenFilter.class.getName());?


public?void?init(FilterConfig?config)?throws?ServletException?
{?
this.filterConfig?=?config;?
this.TokenConfig?=?config.getInitParameter("tokenfile");?
logger.debug("Tokenlist?init?OK!");?
}?


/**?*//**?
*?初始化系統的xml文件,讀入令牌列表?
*/?

@SuppressWarnings(
{?"unchecked",?"deprecation"?})?

public?void?initConfig(ServletRequest?srequest)?
{?

HttpServletRequest?httpRequest?=?(HttpServletRequest)?srequest;?

try?
{?

TokenMap?=?new?HashMap();?
ErrorMap?=?new?HashMap();?

SAXReader?reader?=?new?SAXReader();?
Document?document?=?reader.read(httpRequest.getRealPath(this.TokenConfig));?
List?list1?=?document.getRootElement().selectNodes("/TokenList/Token/TokenForm");?
List?list2?=?document.getRootElement().selectNodes("/TokenList/Token/TokenAction");?
List?list3?=?document.getRootElement().selectNodes("/TokenList/Token/ErrorPage");?

Iterator?iter1?=?list1.iterator();?
Iterator?iter2?=?list2.iterator();?
Iterator?iter3?=?list3.iterator();?

while?(iter1.hasNext()&&iter2.hasNext()&&iter3.hasNext())?
{?
Element?element1?=?(Element)?iter1.next();?
Element?element2?=?(Element)?iter2.next();?
Element?element3?=?(Element)?iter3.next();?
TokenMap.put(element1.getStringValue(),?element2.getStringValue());?
ErrorMap.put(element1.getStringValue(),?element3.getStringValue());?
}?
logger.debug("TokenFilter?Read?"?
+?httpRequest.getRealPath(this.TokenConfig)?
+?"?is?OK!");?

}?catch?(Exception?e)?
{?
logger.error("TokenFilter?Read?"?
+?httpRequest.getRealPath(this.TokenConfig)?
+?"?is?Error!");?
}?

}?

public?void?doFilter(ServletRequest?srequest,?ServletResponse?sresponse,?

FilterChain?chain)?throws?IOException,?ServletException?
{?

HttpServletRequest?httpRequest?=?(HttpServletRequest)?srequest;?


try?
{?
//取出實際的文件路徑直接調用文件,如index.html,login.jsp等?
String?toURI?=?httpRequest.getRequestURI().replaceFirst(httpRequest.getContextPath(),?"");?
if?(TokenMap==null)?


{?
initConfig(httpRequest);?
}?
//檢測為提交jsp頁?
if?(TokenMap.get(toURI)?!=?null)?


{?
FromTokenAction?token?=?new?FromTokenAction();?
token.execute(null,?null,?srequest,?sresponse);?
httpRequest.getSession().setAttribute("PRE_TOKEN_FORM",?toURI);?
logger.debug("TokenFilter?save?'"+toURI?+"'?at?'PRE_TOKEN_FORM'?of?Session!");?
logger.debug("TokenFilter?saveToken?to?'"+toURI?+"'?is?OK!");?
chain.doFilter(srequest,?sresponse);?
return;?
}?

@SuppressWarnings("unused")?
String?preURI?=(String)httpRequest.getSession().getAttribute("PRE_TOKEN_FORM");?
//檢測到為Action接收提交頁面?
if?(TokenMap.get(preURI).equals(toURI))?


{?
TOTokenAction?token?=?new?TOTokenAction();?
token.execute(null,?null,?srequest,?sresponse);?
chain.doFilter(srequest,?sresponse);?
return;?
}?


}?catch?(Exception?e)?


{?
logger.error(e);?
}?

chain.doFilter(srequest,?sresponse);?
}?


public?void?setFilterConfig(final?FilterConfig?filterConfig)?
{?
this.filterConfig?=?filterConfig;?
}?


public?void?destroy()?
{?
TokenMap.clear();?
ErrorMap.clear();?
this.filterConfig?=?null;?
}?

//檢測到需要令牌增加一個令牌?

public?class?FromTokenAction?extends?Action?
{?
public?ActionForward?execute(ActionMapping?mapping,?ActionForm?form,?

HttpServletRequest?request,?HttpServletResponse?response)?
{?
this.saveToken(request);?
return?null;?
}?
}?

//到達Action前檢測令牌?

public?class?TOTokenAction?extends?Action?
{?
public?ActionForward?execute(ActionMapping?mapping,?ActionForm?form,?

HttpServletRequest?request,?HttpServletResponse?response)?
{?
@SuppressWarnings("unused")?
String?preURI?=(String)request.getSession().getAttribute("PRE_TOKEN_FORM");?
//如果檢測令牌錯誤執行錯誤頁,正確將繼續執行?
if?(!isTokenValid(request,?true))?


{?
@SuppressWarnings("unused")?
String?toURI?=?(String)ErrorMap.get(preURI);?
if?(toURI!=null)?


{?
RequestDispatcher?disp?=?request.getRequestDispatcher(toURI);?

try?
{?
disp.forward(request,?response);?

}catch(Exception?e)?


{?
logger.error(e);?
}?
}?
}?
return?null;?
}?
}?

}?

Web.xml的配制
<!--?令牌自動加載配制?-->?
<filter>?
<filter-name>tokenFilter</filter-name>?
<filter-class>com.yapulan.util.filter.TokenFilter</filter-class>?
<init-param>?
<param-name>tokenfile</param-name>?
<param-value>/WEB-INF/TokenConfig.xml</param-value>?
</init-param>?
</filter>?


注意:將代碼包中web.xml做以下修改:
<filter-mapping>?
<filter-name>tokenFilter</filter-name>?
<url-pattern/*</url-pattern>?
</filter-mapping>?

設置好過濾器,只要配置列表即可避免所有的重復提交問題,不必在編程時再次考慮了
<?xml?version="1.0"?encoding="UTF-8"?>?
<TokenList?xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"?xsi:noNamespaceSchemaLocation="TokenConfig.xsd">?
<Token>?
<TokenForm>/index.jsp</TokenForm>?
<TokenAction>/TokenAction.do</TokenAction>?
<ErrorPage>/error.html</ErrorPage>?
</Token>?
<Token>?
<TokenForm>/index1.jsp</TokenForm>?
<TokenAction>/TokenAction1.do</TokenAction>?
<ErrorPage>/error1.jsp</ErrorPage>?
</Token>?
<Token>?
<TokenForm>/index2.jsp</TokenForm>?
<TokenAction>/TokenAction2.do</TokenAction>?
<ErrorPage>/error2.jsp</ErrorPage>?
</Token>?
<Token>?
<TokenForm>/index3.jsp</TokenForm>?
<TokenAction>/TokenAction3.do</TokenAction>?
<ErrorPage>/error3.jsp</ErrorPage>?
</Token>?
</TokenList>?注意:本代碼可以很好的驗證非法的提交,對于管理非法的提交是一個不可多得的具有一定安全意義封裝。
請熱心的朋友分析有無其它沒有考慮的細節問題,并且是否有可以進一部完善的地方,謝謝!
轉自:
http://m.tkk7.com/SE7EN/archive/2008/08/14/222083.html