您的位置:首页 > 编程语言 > Java开发

Spring2.5MVC实现控制重复提交

2012-03-28 10:39 211 查看
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/beanshttp://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}">生成页面唯一编号

 

你这东西貌似不能完全避免重复提交啊。在你替换旧的token之前,可能第二次提交的线程已经过了条件判断。

条件判断那边需要加一个同步锁。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息