通过xml配置搞定Struts重复提交问题

在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> 

 注意:本代码可以很好的验证非法的提交,对于管理非法的提交是一个不可多得的具有一定安全意义封装。
请热心的朋友分析有无其它没有考虑的细节问题,并且是否有可以进一部完善的地方,谢谢! 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值