springmvc的拦截器实现防止用户重复点击按钮
1.当用户访问一个网站提交数据(增上改查按钮)时候由于网络反映较慢,而用户重复点击按钮进入重复提交数据,如何防止这种事情发生呢,基本上是千篇一律均用springmvc的拦截器来实现
本博参考博文:http://blog.csdn.net/u013378306/article/details/52944780 中的第二种方法
这里描述下大概的实现过程:
首先毫无疑问用的肯定是拦截器的preHandle方法,因为这个只有这个方法是在进入controller之前的,如果进入了controller拦截就变的毫意义,对于每一个请求通过preHandle方法中的参数拿到请求的方法名称,再跟进方法名称拿到此方法上是否有定义的标识注解,如果没有标识直接放行,如果有则进行判断是否需要拦截并且把参数放进session中request.getSession().setAttribute("repeatData", url跟参数),以后每一次请求只需要判断当前session中是否有相同的请求参数跟请求地址即可判断用户是否重复提交了数据。
首先定义一个注解,次注解放在controller类中的方法之上,用来表示此请求需要经过拦截器的按钮重复提交验证
package com.thinkgem.jeesite.common.repeat_form_validator; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 一个用户 相同url 同时提交 相同数据 验证 * @author Administrator * */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface SameUrlData { }
核心部分,定义一个springmvc拦截器,用来拦截重复提交的请求
package com.thinkgem.jeesite.common.repeat_form_validator; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; import com.thinkgem.jeesite.common.mapper.JsonMapper; /** * 一个用户 相同url 同时提交 相同数据 验证 * 主要通过 session中保存到的url 和 请求参数。如果和上次相同,则是重复提交表单 * @author Administrator * */ public class SameUrlDataInterceptor extends HandlerInterceptorAdapter{ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { if (handler instanceof HandlerMethod) { HandlerMethod handlerMethod = (HandlerMethod) handler; Method method = handlerMethod.getMethod(); SameUrlData annotation = method.getAnnotation(SameUrlData.class); if (annotation != null) { if(repeatDataValidator(request))//如果重复相同数据 return false; else return true; } return true; } else { return super.preHandle(request, response, handler); } } /** * 验证同一个url数据是否相同提交 ,相同返回true * @param httpServletRequest * @return */ public boolean repeatDataValidator(HttpServletRequest httpServletRequest) { String params=JsonMapper.toJsonString(httpServletRequest.getParameterMap()); String url=httpServletRequest.getRequestURI(); Map<String,String> map=new HashMap<String,String>(); map.put(url, params); String nowUrlParams=map.toString();// Object preUrlParams=httpServletRequest.getSession().getAttribute("repeatData"); if(preUrlParams==null)//如果上一个数据为null,表示还没有访问页面 { httpServletRequest.getSession().setAttribute("repeatData", nowUrlParams); return false; } else//否则,已经访问过页面 { if(preUrlParams.toString().equals(nowUrlParams))//如果上次url+数据和本次url+数据相同,则表示城府添加数据 { return true; } else//如果上次 url+数据 和本次url加数据不同,则不是重复提交 { httpServletRequest.getSession().setAttribute("repeatData", nowUrlParams); return false; } } } }