duansky'weblog

统计

留言簿(3)

友情链接

阅读排行榜

评论排行榜

通过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(
nullnull
, 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(
nullnull
, 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://www.blogjava.net/SE7EN/archive/2008/08/14/222083.html

posted on 2008-11-29 02:22 duansky 阅读(287) 评论(0)  编辑  收藏 所属分类: Java


只有注册用户登录后才能发表评论。


网站导航: