1.实现原理:
提交表单时,从session中取出当前的token值与保存在页面上token值进行比较,如果相等,可以保存表单数据,并将新生成的token保存到session中,如果不相等,则判断为重复提交。
本例采用spring的HandlerInterceptorAdapter拦截器来实现控制重复提交。
2.spring 配置:spring-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<!--
- The controllers are autodetected POJOs labeled with the @Controller annotation.
-->
<context:component-scan base-package="com.allwin" use-default-filters="false" >
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="webBindingInitializer">
<bean class="com.allwin.erp.web.action.common.WebBindingObjectRegister" />
</property>
</bean>
<!--
- This bean configures the 'prefix' and 'suffix' properties of
- InternalResourceViewResolver, which resolves logical view names
- returned by Controllers. For example, a logical view name of "vets"
- will be mapped to "/WEB-INF/jsp/vets.jsp".
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/"
p:suffix=".jsp" />
<context:annotation-config/>
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="defaultEncoding"><value>UTF-8</value></property>
<property name="maxUploadSize">
<value>52428800</value>
</property>
</bean>
<!--
- This bean controller double submit
-->
<bean id="doubleSubmitInterceptor" class="com.allwin.erp.web.action.common.DoubleSubmitInterceptor">
<!--
- 配置要拦截的url
-->
<property name="mappingURL" value=".*/(save|approve|active)\.do" />
<property name="viewURL" value=".*/(view|copy)\.do" />
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list>
<ref bean="doubleSubmitInterceptor"/>
</list>
</property>
</bean>
</beans>
红色字体部分是配置判断重复提交的拦截器
3.java类HandlerInterceptorAdapter.java
public class DoubleSubmitInterceptor extends HandlerInterceptorAdapter {
// matches URL
private String mappingURL;
private String viewURL;
// page number
private static long pageNum = 0l;
/**
* summary: filter request(view/save/approve/active method)
*
* @param : request HttpServletRequest
* @param : response HttpServletResponse
* @param : handler Object
*
* @return boolean true:normal false:double submit
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String url=request.getRequestURL().toString();
// 设置页面编号
if(url.matches(viewURL)){
if(Strings.isEmpty(request.getParameter("pageNum"))){
request.getSession().setAttribute("pageNum",++pageNum);
}
}
if(url.matches(mappingURL)){
// 设置当前token名称(即session中存放token数据的key值)
String tokenName = handler.getClass().getSimpleName() + request.getParameter("pageNum");
// 取得当前session中的token值
String sessionToken = (String)request.getSession().getAttribute(tokenName);
if(sessionToken == null || sessionToken.equals("")){
// 生成新的token
long date = new Date().getTime();
request.getSession().setAttribute(tokenName, request.getSession().getId() + String.valueOf(date));
request.getSession().setAttribute("token", request.getSession().getId() + String.valueOf(date));
request.getSession().setAttribute("pageNum",request.getParameter("pageNum"));
return true;
} else { // 判断是否重复提交(如果session中的token值与request中的token值不一致则判定重复提交)
String requestToken = (String)request.getParameter("token");
if(requestToken == null || !requestToken.equals(sessionToken)){
request.getRequestDispatcher("/front/doubleSubmit.jsp").forward(request, response);
return false;
} else {
// 替换旧的token
long date = new Date().getTime();
request.getSession().setAttribute(tokenName, request.getSession().getId() + String.valueOf(date));
request.getSession().setAttribute("token", request.getSession().getId() + String.valueOf(date));
request.getSession().setAttribute("pageNum",request.getParameter("pageNum"));
return true;
}
}
} else {
return true;
}
}
/**
* @param mappingURL the mappingURL to set
*/
public void setMappingURL(String mappingURL) {
this.mappingURL = mappingURL;
}
/**
* @param viewURL the viewURL to set
*/
public void setViewURL(String viewURL) {
this.viewURL = viewURL;
}
}
4.jsp
在保存数据表单的jsp中加如两个隐藏变量
<input type="hidden" name="token" id="token" value="${token}"> session中的token值
<input type="hidden" name="pageNum" id="pageNum" value="${pageNum}">生成页面唯一编号
分享到:
相关推荐
《Spring 2.5 MVC 完整项目:深入解析与实践》 在IT行业中,Spring框架作为Java领域的重要支柱,其MVC(Model-View-Controller)模块在Web应用程序开发中占据着举足轻重的地位。本文将针对“Spring 2.5 MVC 完整...
总结,Spring 2.5 MVC与iBatis 2的整合应用,既保留了Spring MVC的灵活控制,又充分利用了iBatis的SQL定制能力,是企业级开发中常见的技术栈。理解并掌握这两者的结合,能够提升开发效率,打造高性能的Web应用。
这篇博客"Spring2.5 MVC -- 基于注解的附件上传"详细介绍了如何在Spring MVC 2.5中实现这一功能。 首先,我们需要了解Spring MVC中处理文件上传的基本概念。文件上传主要涉及到两个组件:`MultipartResolver`和`@...
Spring MVC是Spring框架的核心部分,用于构建Web应用程序的模型-视图-控制器(MVC)架构。本主题将深入探讨Spring 2.0、2.5版本的MVC特性和Portlet MVC的相关知识。 首先,Spring 2.0在MVC方面引入了显著的改进,...
Spring MVC 是 Spring 框架的一个重要组成部分,它是一个用于构建 Web 应用程序的模型-视图-控制器(MVC)框架。在 Spring 2.5 版本中,这个框架已经相当成熟,为开发者提供了强大的功能和灵活的配置选项。 ### 1. ...
spring webmvc struts 2.5 spring webmvc struts 2.5 spring webmvc struts 2.5 spring webmvc struts 2.5 spring webmvc struts 2.5 spring webmvc struts 2.5 spring webmvc struts 2.5 spring webmvc struts 2.5 ...
在Spring 2.5 MVC中,还可以利用拦截器(HandlerInterceptor)对请求进行预处理和后处理,实现如权限检查、日志记录等功能。拦截器通过实现HandlerInterceptor接口并配置在DispatcherServlet中,可以在请求处理前后...
《精通Spring2.5》是一本深度探讨Spring框架的权威指南,主要针对Spring 2.5版本进行深入解析。Spring是Java企业级应用开发中最受欢迎的框架之一,它以其轻量级、模块化的设计,以及对IoC(Inversion of Control,...
Spring2.5版本是该框架的一个重要里程碑,它在2008年发布,带来了许多新特性和改进,提升了开发者在构建应用程序时的灵活性和效率。 **依赖注入(DI)和控制反转(IoC)** Spring的核心特性之一是依赖注入(Dependency...
9. **事务管理**:Spring 2.5的事务管理支持包括编程式和声明式两种方式,可以在不侵入业务代码的情况下实现事务的控制。 10. **国际化(i18n)支持**:Spring 2.5提供了更好的国际化支持,使得应用可以轻松地根据...
目前介绍springMVC的资料...本文根据笔者一年多对spring2.5 MVC的学习与实践,将平时的学习笔记进行了整理与完善,对springMVC中涉及到的绝大部分处理管道进行了详细的描述,其中所有列举的配置方式,笔者都做过测试。
Spring 2.5在MVC方面有许多改进,包括对注解的支持,比如`@RequestMapping`、`@Controller`等,使得控制器的定义更加简洁。 7. **国际化(i18n)与本地化(l10n)**: Spring 2.5提供了强大的本地化支持,允许...
Apache CXF和Spring提供了丰富的扩展点,可以集成如Spring Security来控制访问权限,使用Spring AOP来处理事务,以及通过CXF的拦截器机制来实现自定义的日志、验证等功能。 总结来说,Apache CXF 2与Spring 2.5的...
9. **JSR-303 Bean验证**:Spring 2.5开始支持JSR-303标准的bean验证,可以通过注解实现数据校验。 10. **Spring与其他框架的整合**:Spring 2.5增强了与其他框架的集成,如MyBatis、Quartz、EJB等,使得开发者可以...
这个"Spring2.5-中文参考手册chm.zip"文件包含了关于Spring 2.5版本的详细中文指南,对于学习和理解Spring框架具有很高的价值。 Spring框架的核心特性包括依赖注入(Dependency Injection,DI)、面向切面编程...
通过阅读《Spring2.5-中文参考手册.chm》这份文档,开发者可以深入了解Spring 2.5的各种特性和用法,解决实际开发中遇到的问题,提升开发效率。文档不仅包含详细的API参考,还包含丰富的示例和最佳实践指导,是学习...
Spring 2.5引入了一种基于注解的新方式来驱动Spring MVC框架,使得开发者能够更加简洁、直观地配置和管理控制器。这一变化显著提升了开发效率,减少了XML配置文件的复杂性,同时也使得代码更加模块化。 ### 1. 基于...
4. **Web包**:Spring 2.5的Web模块提供了一个全面的MVC框架,支持RESTful风格的Web服务。该模块还包括Servlet监听器、过滤器以及视图解析器等,帮助构建基于HTTP的Web应用。此外,Spring 2.5引入了...
9. **Web应用增强**:Spring 2.5在MVC框架中引入了诸如`@RequestMapping`、`@RequestParam`等注解,简化了控制器方法的映射和参数绑定。 10. **数据访问增强**:Spring 2.5增强了对JDBC、Hibernate、JPA等数据访问...