`
SE7EN
  • 浏览: 3171 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

通过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>

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

相关推荐

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

    在本文中,我们将深入探讨如何通过XML配置来解决Struts中的重复提交问题。 首先,理解重复提交的原因。在Web应用中,用户点击提交按钮后,如果网络延迟或刷新页面,同一个请求可能被发送多次。Struts框架默认情况下...

    struts-config.xml struts标准配置文件 struts-config

    struts-config.xml struts标准配置文件 struts-config

    SSH三大框架整合 struts2(使用xml配置)+hibernate(使用xml配置)+spring(使用xml配置)

    通过定义Action类和对应的配置文件struts.xml,我们可以设置URL映射,指定请求如何转发到特定的方法。在XML配置中,我们可以定义action、result、param等元素,以声明式的方式管理应用程序的行为。 接着,Hibernate...

    Struts2解决表单重复提交

    对于第二种原因,即提交表单后刷新浏览器页面导致的重复提交,Struts2框架允许开发者通过配置结果视图的跳转方式来解决。默认情况下,Struts2使用的是dispatcher类型的forward跳转。为了避免刷新页面导致的重复提交...

    Struts-config.xml配置详解

    通过配置数据源,开发者可以使得数据访问更加灵活和易于管理。 2. 元素:form-beans元素用于配置表单验证相关的JavaBean。这个JavaBean通常对应于一个HTML表单,负责封装表单提交的数据。form-bean可以定义多个属性...

    struts.xml配置文件详解

    通过对`struts.xml`配置文件的详细解析,我们可以看到Struts 2框架的强大之处在于其高度可配置性。开发者可以通过简单的XML配置即可实现复杂的功能需求。了解并掌握这些配置项对于高效开发基于Struts 2的应用程序至...

    Struts2文件上传下载和表单重复提交问题

    首先,要在`struts.xml`配置文件中启用文件上传支持,设置`struts.multipart.parser`为`jakarta`或`native2ascii`。然后,在Action类中创建一个`java.io.File`或者`org.apache.struts2.dispatcher.multipart....

    SSH三大框架整合mini案例 struts 2(xml配置)+hibernate(注解)+spring(xml配置)

    在这个mini案例中,我们将深入理解SSH框架如何协同工作,以实现一个基于XML配置的Struts 2、注解驱动的Hibernate以及XML配置的Spring的整合。 **Struts 2框架** 是一个MVC(Model-View-Controller)架构,主要负责...

    Struts struts-config.xml配置

    通过对`struts-config.xml`配置文件的详细解析,我们可以了解到如何通过不同的元素和属性来配置数据源、表单Bean以及全局异常处理等内容。这对于理解和使用Struts框架来说至关重要。希望本文能帮助读者更好地掌握...

    struts2 防止表单重复提交的例子

    5. **Struts2配置**:在Struts2的配置文件(struts.xml)中,需要添加Token拦截器到Action配置中。例如: ``` ``` 这样,每次请求都会经过Token拦截器的检查。 6. **异常处理**:Struts2提供了`...

    spring在web.xml中和在struts中的不同配置..pdf

    在本文中,我们将探讨Spring在`web.xml`中的配置与在Struts中的配置差异,以及这两种配置方式背后的基本原理。 首先,Spring的核心是ApplicationContext,它是一个管理Bean的容器,可以看作是应用程序的上下文环境...

    struts.xml(struts2配置)

    通过理解和灵活运用`struts.xml`配置,开发者能够构建出高效、可维护的Struts2应用。同时,配合使用Struts提供的插件和标签库,可以进一步提升开发效率。对于初学者,熟练掌握`struts.xml`的配置是学习Struts2的关键...

    struts-config.xml配置文件详解

    在 Struts-config.xml 文件中,数据源配置是通过 `&lt;data-sources&gt;` 元素实现的,该元素可以包含多个 `&lt;data-source&gt;` 子元素,每个 `&lt;data-source&gt;` 元素可以配置一个数据源。数据源配置中可以设置 driverClass、url...

    struts.xml常用配置解析

    Struts.xml配置文件是Struts2框架的核心配置文件,它定义了应用的行为和结构。本文主要解析了其中两个重要的配置元素:`&lt;include&gt;`标签和Action的别名。 首先,我们来看 `&lt;include&gt;` 标签的使用。当Struts2的应用中...

    struts.xml和struts.properties配置详解

    总结,`struts.xml`和`struts.properties`是Struts2框架中至关重要的配置文件,通过它们可以灵活地控制应用的行为和设定。理解并熟练运用这两个文件,对于开发高质量的Struts2应用至关重要。在实际项目中,开发者应...

    struts2 Https 配置

    这可以通过在`struts.xml`配置文件中使用`&lt;constant&gt;`标签设置`struts.action.excludePattern`属性来实现。 ```xml &lt;constant name="struts.action.excludePattern" value="^http://.*"/&gt; ``` 3. **过滤器配置*...

    Struts2中struts_xml的Action配置详解

    总之,`struts_xml`中的Action配置是Struts2应用的基石,通过它可以灵活地定义请求与业务逻辑的映射关系,以及后续的页面跳转和拦截器链,从而构建出高效、可维护的Web应用。深入了解和熟练掌握这部分知识对于提升...

    struts.xml

    struts.xml文件配置解释,对action配置进行说明

    struts.xml详细配置

    Struts.xml是Apache Struts框架的核心配置文件,用于定义应用的行为和控制器的映射。它在MVC(Model-View-Controller)设计...通过熟练掌握Struts.xml的配置,开发者能够创建高效、灵活的Struts2应用,提供稳定的服务。

Global site tag (gtag.js) - Google Analytics