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

在webWork中有Token标签,可以直接搞定重复提交的问题,但在Struts2.0以下的版本,传统的做法只有通过提供的Token编程来搞定,代码虽然不多但是,这样的细节涉及了两个Action,对于页面的跳转控制来说是一个额外的负担,必须处处小心,本文阐述了如何通过Filter通过配置来避免struts的Form重复提交问题。
核心代码如下:

Java代码 复制代码
  1. package com.yapulan.util.filter;    
  2.   
  3. import java.io.IOException;    
  4. import java.util.HashMap;    
  5. import java.util.Iterator;    
  6. import java.util.List;    
  7.   
  8. import javax.servlet.Filter;    
  9. import javax.servlet.RequestDispatcher;    
  10. import javax.servlet.ServletException;    
  11. import javax.servlet.FilterConfig;    
  12. import javax.servlet.http.HttpServletRequest;    
  13. import javax.servlet.http.HttpServletResponse;    
  14. import javax.servlet.FilterChain;    
  15. import javax.servlet.ServletRequest;    
  16. import javax.servlet.ServletResponse;    
  17.   
  18. import org.apache.log4j.Logger;    
  19. import org.apache.struts.action.Action;    
  20. import org.apache.struts.action.ActionForm;    
  21. import org.apache.struts.action.ActionForward;    
  22. import org.apache.struts.action.ActionMapping;    
  23. import org.dom4j.Document;    
  24. import org.dom4j.Element;    
  25. import org.dom4j.io.SAXReader;    
  26.   
  27. /**   
  28. * 重复提交令牌自动加载器 功能:读取过滤器中设置的信息,读入令牌设置组   
  29. */    
  30.   
  31. public class TokenFilter implements Filter {    
  32.   
  33. private String TokenConfig = "TokenConfig.xml";    
  34. private HashMap TokenMap = null;    
  35. private HashMap ErrorMap = null;    
  36. protected FilterConfig filterConfig;    
  37. static Logger logger = Logger.getLogger(TokenFilter.class.getName());    
  38.   
  39. public void init(FilterConfig config) throws ServletException {    
  40. this.filterConfig = config;    
  41. this.TokenConfig = config.getInitParameter("tokenfile");    
  42. logger.debug("Tokenlist init OK!");    
  43. }    
  44.   
  45. /**   
  46. * 初始化系统的xml文件,读入令牌列表   
  47. */    
  48. @SuppressWarnings({ "unchecked""deprecation" })    
  49. public void initConfig(ServletRequest srequest) {    
  50.   
  51. HttpServletRequest httpRequest = (HttpServletRequest) srequest;    
  52. try {    
  53.   
  54. TokenMap = new HashMap();    
  55. ErrorMap = new HashMap();    
  56.   
  57. SAXReader reader = new SAXReader();    
  58. Document document = reader.read(httpRequest.getRealPath(this.TokenConfig));    
  59. List list1 = document.getRootElement().selectNodes("/TokenList/Token/TokenForm");    
  60. List list2 = document.getRootElement().selectNodes("/TokenList/Token/TokenAction");    
  61. List list3 = document.getRootElement().selectNodes("/TokenList/Token/ErrorPage");    
  62.   
  63. Iterator iter1 = list1.iterator();    
  64. Iterator iter2 = list2.iterator();    
  65. Iterator iter3 = list3.iterator();    
  66. while (iter1.hasNext()&&iter2.hasNext()&&iter3.hasNext()) {    
  67. Element element1 = (Element) iter1.next();    
  68. Element element2 = (Element) iter2.next();    
  69. Element element3 = (Element) iter3.next();    
  70. TokenMap.put(element1.getStringValue(), element2.getStringValue());    
  71. ErrorMap.put(element1.getStringValue(), element3.getStringValue());    
  72. }    
  73. logger.debug("TokenFilter Read "    
  74. + httpRequest.getRealPath(this.TokenConfig)    
  75. " is OK!");    
  76. catch (Exception e) {    
  77. logger.error("TokenFilter Read "    
  78. + httpRequest.getRealPath(this.TokenConfig)    
  79. " is Error!");    
  80. }    
  81.   
  82. }    
  83.   
  84. public void doFilter(ServletRequest srequest, ServletResponse sresponse,    
  85. FilterChain chain) throws IOException, ServletException {    
  86.   
  87. HttpServletRequest httpRequest = (HttpServletRequest) srequest;    
  88.   
  89. try {    
  90. //取出实际的文件路径直接调用文件,如index.html,login.jsp等    
  91. String toURI = httpRequest.getRequestURI().replaceFirst(httpRequest.getContextPath(), "");    
  92. if (TokenMap==null)    
  93. {    
  94. initConfig(httpRequest);    
  95. }    
  96. //检测为提交jsp页    
  97. if (TokenMap.get(toURI) != null)    
  98. {    
  99. FromTokenAction token = new FromTokenAction();    
  100. token.execute(nullnull, srequest, sresponse);    
  101. httpRequest.getSession().setAttribute("PRE_TOKEN_FORM", toURI);    
  102. logger.debug("TokenFilter save '"+toURI +"' at 'PRE_TOKEN_FORM' of Session!");    
  103. logger.debug("TokenFilter saveToken to '"+toURI +"' is OK!");    
  104. chain.doFilter(srequest, sresponse);    
  105. return;    
  106. }    
  107.   
  108. @SuppressWarnings("unused")    
  109. String preURI =(String)httpRequest.getSession().getAttribute("PRE_TOKEN_FORM");    
  110. //检测到为Action接收提交页面    
  111. if (TokenMap.get(preURI).equals(toURI))    
  112. {    
  113. TOTokenAction token = new TOTokenAction();    
  114. token.execute(nullnull, srequest, sresponse);    
  115. chain.doFilter(srequest, sresponse);    
  116. return;    
  117. }    
  118.   
  119.   
  120. catch (Exception e)    
  121. {    
  122. logger.error(e);    
  123. }    
  124.   
  125. chain.doFilter(srequest, sresponse);    
  126. }    
  127.   
  128. public void setFilterConfig(final FilterConfig filterConfig) {    
  129. this.filterConfig = filterConfig;    
  130. }    
  131.   
  132. public void destroy() {    
  133. TokenMap.clear();    
  134. ErrorMap.clear();    
  135. this.filterConfig = null;    
  136. }    
  137.   
  138. //检测到需要令牌增加一个令牌    
  139. public class FromTokenAction extends Action {    
  140. public ActionForward execute(ActionMapping mapping, ActionForm form,    
  141. HttpServletRequest request, HttpServletResponse response) {    
  142. this.saveToken(request);    
  143. return null;    
  144. }    
  145. }    
  146.   
  147. //到达Action前检测令牌    
  148. public class TOTokenAction extends Action {    
  149. public ActionForward execute(ActionMapping mapping, ActionForm form,    
  150. HttpServletRequest request, HttpServletResponse response) {    
  151. @SuppressWarnings("unused")    
  152. String preURI =(String)request.getSession().getAttribute("PRE_TOKEN_FORM");    
  153. //如果检测令牌错误执行错误页,正确将继续执行    
  154. if (!isTokenValid(request, true))    
  155. {    
  156. @SuppressWarnings("unused")    
  157. String toURI = (String)ErrorMap.get(preURI);    
  158. if (toURI!=null)    
  159. {    
  160. RequestDispatcher disp = request.getRequestDispatcher(toURI);    
  161. try {    
  162. disp.forward(request, response);    
  163.   
  164. }catch(Exception e)    
  165. {    
  166. logger.error(e);    
  167. }    
  168. }    
  169. }    
  170. return null;    
  171. }    
  172. }    
  173.   
  174. }   
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的配制 

Java代码 复制代码
  1. <!-- 令牌自动加载配制 -->    
  2. <filter>    
  3.         <filter-name>tokenFilter</filter-name>    
  4.         <filter-class>com.yapulan.util.filter.TokenFilter</filter-class>    
  5.     <init-param>    
  6.     <param-name>tokenfile</param-name>    
  7.     <param-value>/WEB-INF/TokenConfig.xml</param-value>    
  8.     </init-param>    
  9.      </filter>    
  10.        
  11.     注意:将代码包中web.xml做以下修改    
  12.     <filter-mapping>    
  13.        <filter-name>tokenFilter</filter-name>    
  14.        <url-pattern/*</url-pattern>     
  15.      </filter-mapping>    
  16.         
  17.     
<!-- 令牌自动加载配制 --> 
<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> 
     
  

 设置好过滤器,只要配置列表即可避免所有的重复提交问题,不必在编程时再次考虑了

Java代码 复制代码
  1. <?xml version="1.0" encoding="UTF-8"?>    
  2. <TokenList xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="TokenConfig.xsd">    
  3. <Token>    
  4. <TokenForm>/index.jsp</TokenForm>    
  5. <TokenAction>/TokenAction.do</TokenAction>    
  6. <ErrorPage>/error.html</ErrorPage>    
  7. </Token>    
  8. <Token>    
  9. <TokenForm>/index1.jsp</TokenForm>    
  10. <TokenAction>/TokenAction1.do</TokenAction>    
  11. <ErrorPage>/error1.jsp</ErrorPage>    
  12. </Token>    
  13. <Token>    
  14. <TokenForm>/index2.jsp</TokenForm>    
  15. <TokenAction>/TokenAction2.do</TokenAction>    
  16. <ErrorPage>/error2.jsp</ErrorPage>    
  17. </Token>    
  18. <Token>    
  19. <TokenForm>/index3.jsp</TokenForm>    
  20. <TokenAction>/TokenAction3.do</TokenAction>    
  21. <ErrorPage>/error3.jsp</ErrorPage>    
  22. </Token>    
  23. </TokenList>   
<?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> 

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值