spring-mvc拦截器+注解 解决重复请求

来源:互联网 发布:编程熟练 编辑:程序博客网 时间:2024/06/05 20:51

在实际生产环境中,首次保存信息,点击一次保存按钮可服务器响应较慢,客户心急多次点击保存按钮,就会导致保存多分除ID外一模一样的信息,这是一个较为严重的bug

怎么解决?f不多说,这是我总结实现的代码

第一步:写一个拦截器,    验证请求内容是否完全相同

package com.thinkgem.jeesite.common.interceptor;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.apache.log4j.Logger;import org.springframework.web.context.request.RequestContextHolder;import org.springframework.web.context.request.ServletRequestAttributes;import org.springframework.web.method.HandlerMethod;  import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;  import com.thinkgem.jeesite.common.mapper.JsonMapper;   /** 16. * 一个用户 相同url 同时提交 相同数据 验证 17. * 主要通过 session中保存到的url 和 请求参数。如果和上次相同,则是重复提交表单 18. * @author Administrator 19. * 20. */  public class SameUrlDataInterceptor  extends HandlerInterceptorAdapter{  private static final Logger LOG = Logger.getLogger(SameUrlData.class);    /**      * 是否阻止提交 ,fasle 阻止  ,true放行     * @param httpServletRequest      * @return     */      @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)){                     LOG.warn("please don't repeat submit,url:"+ request.getServletPath());                                                   String id = request.getParameter("id");                          if(id!=null&&!"".equals(id)){//如果信息表ID已经存在则不是新加信息,而是修改信息,放行                          return true;                          }                          String formRequest = request.getRequestURI();                          request.setAttribute("myurl", formRequest);                          request.getRequestDispatcher("/WEB-INF/views/modules/middle/middle.jsp").forward(request, response);//拦截之后页面跳转位置                           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=IdGen.generateShortUuid();String params=JsonMapper.toJsonString(httpServletRequest.getParameterMap()); //获取全部请求内容Object[] urlFlags = (Object[]) httpServletRequest.getParameterMap().get("urlFlag"); //获取不可变标识       System.out.println("params==========="+params);            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;             }                       }      }    }  


第二步:把拦截器写成注解

package com.thinkgem.jeesite.common.interceptor;import java.lang.annotation.ElementType;  import java.lang.annotation.Retention;  import java.lang.annotation.RetentionPolicy;  import java.lang.annotation.Target;   /** 09. * 一个用户 相同url 同时提交 相同数据 验证 10. * @author Administrator 11. * 12. */  @Target(ElementType.METHOD)  @Retention(RetentionPolicy.RUNTIME)  public @interface SameUrlData {          } 

第三步:把拦截器路径写在spring-mvc的配置文件中

<!-- 配置拦截器,防止用户重复提交数据 --><!--拦截得路径 拦截所有得URL--><!--class文件路径改成你自己写得拦截器路径!!--><mvc:interceptor>            <mvc:mapping path="${adminPath}/wkst/worksheet/save"/>              <mvc:mapping path="${adminPath}/cust/customer/save"/>              <bean class="com.thinkgem.jeesite.common.interceptor.SameUrlDataInterceptor"/> </mvc:interceptor> 

第四步:把注解写在controller的最前面

@SameUrlData@RequiresPermissions("cust:customer:edit")@RequestMapping(value = "save")public String save(Customer customer, Model model,HttpServletRequest request, RedirectAttributes redirectAttributes)

第五步:在页面写URL标识
<input type="hidden" name="urlFlag" value="${urlFlag}">    //在打开页面的时候就存一个唯一标识,UUID <form:hidden path="id"/>//信息表生成的ID

第六部:写拦截到重复请求页面跳转的位置  

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%String path = request.getContextPath();String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";%><%@ include file="/WEB-INF/views/include/taglib.jsp"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html>  <head>    <base href="<%=basePath%>">        <title>My JSP 'middle.jsp' starting page</title>    <meta http-equiv="pragma" content="no-cache"><meta http-equiv="cache-control" content="no-cache"><meta http-equiv="expires" content="0">    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"><meta http-equiv="description" content="This is my page"><!--<link rel="stylesheet" type="text/css" href="styles.css">--><script type="text/javascript">function readyLoad(){var url = "${myurl}";if(url.indexOf('/wkst/worksheet/save')>=0){setTimeout(function(){window.location.href = "${ctx}/wkst/worksheet/autosave";}, 2000 );} else if(url.indexOf('/cust/customer/save')>=0){setTimeout(function(){window.location.href = "${ctx}/cust/customer/list";}, 2000 );}}</script>  </head>    <body onload="readyLoad()">  </body></html>



至此,宝宝再也不担心重复提交了,吐槽一下,这编辑器有bug,我改了8遍,不能优化吗?


阅读全文
0 0
原创粉丝点击