zoukankan      html  css  js  c++  java
  • spring mvc 防止重复提交表单的两种方法,推荐第二种

    第一种方法:判断session中保存的token

    比较麻烦,每次在提交表单时都必须传入上次的token。而且当一个页面使用ajax时,多个表单提交就会有问题。

    注解Token代码:

    1. package com.thinkgem.jeesite.common.repeat_form_validator;  
    2.   
    3. import java.lang.annotation.ElementType;  
    4. import java.lang.annotation.Retention;  
    5. import java.lang.annotation.RetentionPolicy;  
    6. import java.lang.annotation.Target;  
    7.   
    8. /** 
    9.  * 页面form   token 
    10.  * @author Administrator 
    11.  * 
    12.  */  
    13. @Target(ElementType.METHOD)  
    14. @Retention(RetentionPolicy.RUNTIME)  
    15. public @interface FormToken {  
    16.   
    17.     boolean save() default false;  
    18.   
    19.     boolean remove() default false;  
    20. }  


    拦截器TokenInterceptor代码:

    1. package com.thinkgem.jeesite.common.repeat_form_validator;  
    2.   
    3. import java.lang.reflect.Method;  
    4. import java.util.UUID;  
    5.   
    6. import javax.servlet.http.HttpServletRequest;  
    7. import javax.servlet.http.HttpServletResponse;  
    8.   
    9. import org.springframework.web.method.HandlerMethod;  
    10. import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;  
    11.   
    12. public class FormTokenInterceptor extends HandlerInterceptorAdapter {  
    13.   
    14.     @Override  
    15.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  
    16.         if (handler instanceof HandlerMethod) {  
    17.             HandlerMethod handlerMethod = (HandlerMethod) handler;  
    18.             Method method = handlerMethod.getMethod();  
    19.             FormToken annotation = method.getAnnotation(FormToken.class);  
    20.             if (annotation != null) {  
    21.                 boolean needSaveSession = annotation.save();  
    22.                 if (needSaveSession) {  
    23.                     request.getSession(false).setAttribute("formToken", UUID.randomUUID().toString());  
    24.                 }  
    25.                 boolean needRemoveSession = annotation.remove();  
    26.                 if (needRemoveSession) {  
    27.                     if (isRepeatSubmit(request)) {  
    28.                         return false;  
    29.                     }  
    30.                     request.getSession(false).removeAttribute("formToken");  
    31.                 }  
    32.             }  
    33.             return true;  
    34.         } else {  
    35.             return super.preHandle(request, response, handler);  
    36.         }  
    37.     }  
    38.   
    39.     private boolean isRepeatSubmit(HttpServletRequest request) {  
    40.         String serverToken = (String) request.getSession(false).getAttribute("formToken");  
    41.         if (serverToken == null) {  
    42.             return true;  
    43.         }  
    44.         String clinetToken = request.getParameter("formToken");  
    45.         if (clinetToken == null) {  
    46.             return true;  
    47.         }  
    48.         if (!serverToken.equals(clinetToken)) {  
    49.             return true;  
    50.         }  
    51.         return false;  
    52.     }  
    53. }  

    然后在Spring MVC的配置文件里加入:

    1. <mvc:interceptors>  
    2.     <mvc:interceptor>  
    3.             <mvc:mapping path="/**"/>  
    4.             <bean class="com.thinkgem.jeesite.common.repeat_form_validator.FormTokenInterceptor"/>  
    5.         </mvc:interceptor>  
    6.     </mvc:interceptors>  


    相关代码已经注释,相信你能看懂。
    关于这个方法的用法是:
    在需要生成token的controller上增加@FormToken(save=true),而在需要检查重复提交的controller上添加@FormToken(remove=true)就可以了。
    另外,你需要在view里在form里增加下面代码:

    1. <inputtypeinputtype="hidden"name="formToken"value="${formToken}" />  

    已经完成了,去试试看你的数据还能重复提交了吧。

    注意在ajax提交时 要加上 formToken参数

    第二种方法(判断请求url和数据是否和上一次相同)

    推荐,非常简单,页面不需要任何传入,只需要在验证的controller方法上写上自定义注解即可

    写好自定义注解

    1. package com.thinkgem.jeesite.common.repeat_form_validator;  
    2.   
    3. import java.lang.annotation.ElementType;  
    4. import java.lang.annotation.Retention;  
    5. import java.lang.annotation.RetentionPolicy;  
    6. import java.lang.annotation.Target;  
    7.   
    8. /** 
    9.  * 一个用户 相同url 同时提交 相同数据 验证 
    10.  * @author Administrator 
    11.  * 
    12.  */  
    13. @Target(ElementType.METHOD)  
    14. @Retention(RetentionPolicy.RUNTIME)  
    15. public @interface SameUrlData {  
    16.   
    17.       
    18. }  


    写好拦截器

    1. package com.thinkgem.jeesite.common.repeat_form_validator;  
    2.   
    3. import java.lang.reflect.Method;  
    4. import java.util.HashMap;  
    5. import java.util.Map;  
    6.   
    7. import javax.servlet.http.HttpServletRequest;  
    8. import javax.servlet.http.HttpServletResponse;  
    9.   
    10. import org.springframework.web.method.HandlerMethod;  
    11. import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;  
    12.   
    13. import com.thinkgem.jeesite.common.mapper.JsonMapper;  
    14.   
    15. /** 
    16.  * 一个用户 相同url 同时提交 相同数据 验证 
    17.  * 主要通过 session中保存到的url 和 请求参数。如果和上次相同,则是重复提交表单 
    18.  * @author Administrator 
    19.  * 
    20.  */  
    21. public class SameUrlDataInterceptor  extends HandlerInterceptorAdapter{  
    22.       
    23.       @Override  
    24.         public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  
    25.             if (handler instanceof HandlerMethod) {  
    26.                 HandlerMethod handlerMethod = (HandlerMethod) handler;  
    27.                 Method method = handlerMethod.getMethod();  
    28.                 SameUrlData annotation = method.getAnnotation(SameUrlData.class);  
    29.                 if (annotation != null) {  
    30.                     if(repeatDataValidator(request))//如果重复相同数据  
    31.                         return false;  
    32.                     else   
    33.                         return true;  
    34.                 }  
    35.                 return true;  
    36.             } else {  
    37.                 return super.preHandle(request, response, handler);  
    38.             }  
    39.         }  
    40.     /** 
    41.      * 验证同一个url数据是否相同提交  ,相同返回true 
    42.      * @param httpServletRequest 
    43.      * @return 
    44.      */  
    45.     public boolean repeatDataValidator(HttpServletRequest httpServletRequest)  
    46.     {  
    47.         String params=JsonMapper.toJsonString(httpServletRequest.getParameterMap());  
    48.         String url=httpServletRequest.getRequestURI();  
    49.         Map<String,String> map=new HashMap<String,String>();  
    50.         map.put(url, params);  
    51.         String nowUrlParams=map.toString();//  
    52.           
    53.         Object preUrlParams=httpServletRequest.getSession().getAttribute("repeatData");  
    54.         if(preUrlParams==null)//如果上一个数据为null,表示还没有访问页面  
    55.         {  
    56.             httpServletRequest.getSession().setAttribute("repeatData", nowUrlParams);  
    57.             return false;  
    58.         }  
    59.         else//否则,已经访问过页面  
    60.         {  
    61.             if(preUrlParams.toString().equals(nowUrlParams))//如果上次url+数据和本次url+数据相同,则表示城府添加数据  
    62.             {  
    63.                   
    64.                 return true;  
    65.             }  
    66.             else//如果上次 url+数据 和本次url加数据不同,则不是重复提交  
    67.             {  
    68.                 httpServletRequest.getSession().setAttribute("repeatData", nowUrlParams);  
    69.                 return false;  
    70.             }  
    71.               
    72.         }  
    73.     }  
    74.   
    75. }  


    配置spring mvc

    1. <mvc:interceptor>  
    2.            <mvc:mapping path="/**"/>  
    3.            <bean class="com.thinkgem.jeesite.common.repeat_form_validator.SameUrlDataInterceptor"/>  
    4.        </mvc:interceptor>  


  • 相关阅读:
    Android 开发 深入理解Handler、Looper、Messagequeue 转载
    Android 开发 Handler的基本使用
    Java 学习 注解
    Android 开发 AlarmManager 定时器
    Android 开发 框架系列 百度语音合成
    Android 开发 框架系列 Google的ORM框架 Room
    Android 开发 VectorDrawable 矢量图 (三)矢量图动画
    Android 开发 VectorDrawable 矢量图 (二)了解矢量图属性与绘制
    Android 开发 VectorDrawable 矢量图 (一)了解Android矢量图与获取矢量图
    Android 开发 知晓各种id信息 获取线程ID、activityID、内核ID
  • 原文地址:https://www.cnblogs.com/jpfss/p/8072516.html
Copyright © 2011-2022 走看看