在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>
注意:本代码可以很好的验证非法的提交,对于管理非法的提交是一个不可多得的具有一定安全意义封装。
请热心的朋友分析有无其它没有考虑的细节问题,并且是否有可以进一部完善的地方,谢谢!
分享到:
相关推荐
struts-config.xml struts标准配置文件 struts-config
通过定义Action类和对应的配置文件struts.xml,我们可以设置URL映射,指定请求如何转发到特定的方法。在XML配置中,我们可以定义action、result、param等元素,以声明式的方式管理应用程序的行为。 接着,Hibernate...
对于第二种原因,即提交表单后刷新浏览器页面导致的重复提交,Struts2框架允许开发者通过配置结果视图的跳转方式来解决。默认情况下,Struts2使用的是dispatcher类型的forward跳转。为了避免刷新页面导致的重复提交...
在Web开发中,尤其是使用Struts2框架时,防止重复提交是一个重要的问题,因为它可能导致数据的不一致性或者服务器资源的浪费。Struts2提供了一种通过拦截器来解决这个问题的方法,即`token`拦截器。本文将深入探讨...
### Struts框架中struts-config.xml文件配置详解 #### 一、引言 在Java Web开发领域,Struts是一个非常重要的MVC(Model-View-Controller)框架,它极大地简化了Web应用程序的开发过程。而在Struts框架中,`struts...
通过配置数据源,开发者可以使得数据访问更加灵活和易于管理。 2. 元素:form-beans元素用于配置表单验证相关的JavaBean。这个JavaBean通常对应于一个HTML表单,负责封装表单提交的数据。form-bean可以定义多个属性...
通过对`struts.xml`配置文件的详细解析,我们可以看到Struts 2框架的强大之处在于其高度可配置性。开发者可以通过简单的XML配置即可实现复杂的功能需求。了解并掌握这些配置项对于高效开发基于Struts 2的应用程序至...
Ajax struts2 xml flex Ajax struts2 xml flex Ajax struts2 xml flex Ajax struts2 xml flex Ajax struts2 xml flex Ajax struts2 xml flex
综上所述,Struts2文件上传下载和表单重复提交涉及多个技术点,包括Struts2的配置、文件操作、HTTP响应头设置、安全性和异常处理。理解并熟练掌握这些知识点,对于构建健壮的Web应用程序至关重要。
5. **Struts2配置**:在Struts2的配置文件(struts.xml)中,需要添加Token拦截器到Action配置中。例如: ``` ``` 这样,每次请求都会经过Token拦截器的检查。 6. **异常处理**:Struts2提供了`...
通过对`struts-config.xml`配置文件的详细解析,我们可以了解到如何通过不同的元素和属性来配置数据源、表单Bean以及全局异常处理等内容。这对于理解和使用Struts框架来说至关重要。希望本文能帮助读者更好地掌握...
本压缩包包含了Struts2的核心库jar文件以及相关的XML配置文件,这些都是开发Struts2应用的基础组件。 **1. Struts2核心jar包** Struts2的核心jar包是实现框架功能的关键,主要包括以下几个部分: - **struts2-core...
在本文中,我们将探讨Spring在`web.xml`中的配置与在Struts中的配置差异,以及这两种配置方式背后的基本原理。 首先,Spring的核心是ApplicationContext,它是一个管理Bean的容器,可以看作是应用程序的上下文环境...
通过理解和灵活运用`struts.xml`配置,开发者能够构建出高效、可维护的Struts2应用。同时,配合使用Struts提供的插件和标签库,可以进一步提升开发效率。对于初学者,熟练掌握`struts.xml`的配置是学习Struts2的关键...
Struts2-Spring4-Hibernate4 XML配置的框架是一个经典的Java Web开发架构,它整合了三个主流的开源框架:Struts2、Spring4和Hibernate4。这个框架的配置主要通过XML文件来完成,同时也可以结合注解的方式进行更加...
以前和struts2一起使用的配置文件,struts2的核心控制器
"Struts2 中 Struts.xml 配置文件详解" Struts2 中的 Struts.xml 配置文件是 Struts2 框架的核心配置文件,用于定义应用程序的行为和结构。在 Struts.xml 文件中,我们可以定义 package、action、interceptor、...
这可以通过在`struts.xml`配置文件中使用`<constant>`标签设置`struts.action.excludePattern`属性来实现。 ```xml <constant name="struts.action.excludePattern" value="^http://.*"/> ``` 3. **过滤器配置*...
总结,`struts.xml`和`struts.properties`是Struts2框架中至关重要的配置文件,通过它们可以灵活地控制应用的行为和设定。理解并熟练运用这两个文件,对于开发高质量的Struts2应用至关重要。在实际项目中,开发者应...