在webWork中有Token標(biāo)簽,可以直接搞定重復(fù)提交的問題,但在Struts2.0以下的版本,傳統(tǒng)的做法只有通過提供的Token編程來搞定,代碼雖然不多但是,這樣的細(xì)節(jié)涉及了兩個(gè)Action,對(duì)于頁(yè)面的跳轉(zhuǎn)控制來說是一個(gè)額外的負(fù)擔(dān),必須處處小心,本文闡述了如何通過Filter通過配置來避免struts的Form重復(fù)提交問題。
核心代碼如下:
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;?


/**?*//**?
*?重復(fù)提交令牌自動(dòng)加載器?功能:讀取過濾器中設(shè)置的信息,讀入令牌設(shè)置組?
*/?


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!");?
}?


/**?*//**?
*?初始化系統(tǒng)的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?
{?
//取出實(shí)際的文件路徑直接調(diào)用文件,如index.html,login.jsp等?
String?toURI?=?httpRequest.getRequestURI().replaceFirst(httpRequest.getContextPath(),?"");?
if?(TokenMap==null)?


{?
initConfig(httpRequest);?
}?
//檢測(cè)為提交jsp頁(yè)?
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");?
//檢測(cè)到為Action接收提交頁(yè)面?
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;?
}?

//檢測(cè)到需要令牌增加一個(gè)令牌?

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

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

//到達(dá)Action前檢測(cè)令牌?

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");?
//如果檢測(cè)令牌錯(cuò)誤執(zhí)行錯(cuò)誤頁(yè),正確將繼續(xù)執(zhí)行?
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的配制
<!--?令牌自動(dòng)加載配制?-->?
<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>?

設(shè)置好過濾器,只要配置列表即可避免所有的重復(fù)提交問題,不必在編程時(shí)再次考慮了
<?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>?注意:本代碼可以很好的驗(yàn)證非法的提交,對(duì)于管理非法的提交是一個(gè)不可多得的具有一定安全意義封裝。
請(qǐng)熱心的朋友分析有無其它沒有考慮的細(xì)節(jié)問題,并且是否有可以進(jìn)一部完善的地方,謝謝!
轉(zhuǎn)自:
http://www.aygfsteel.com/SE7EN/archive/2008/08/14/222083.html