常见的表单重复提交的应用场景1.在网络延迟的情况下,用户多次点击提交按钮,导致2.表单提交后,用户点击刷新按钮,导致表单刷新重复提交3、用户表单提交后,点击浏览器后退按钮返回表单页面,然后重新提交。很多时候,重复提交的数据并不是我们想要的,比如订单的提交,退款申请的提交等,那么如何防止重新提交呢?下面介绍4种方法,重点介绍最后一种:1.对数据库需要的字段添加唯一约束。这种方式是防止数据重复提交最有效的方法,但是前台还是会出现重复提交的情况。背景报告是错误的。2.点击按钮提交后前端用js设置disable,然后orjs设置一个属性,提交前为true,提交后为false。客户端禁用js,该方法将失效3、使用Post/Redirect/Get Post/Redirect/Get,简称PRG,是一种网页设计模式,可以防止重复提交表单数据。使用PRG模式可以避免用户刷新和提交响应页面等典型问题。例如:用户提交成功后,进行客户端重定向,跳转到提交成功页面。 注意:PRG设计模式并不适用于所有重复提交的情况,例如: 1)由于服务器响应慢,用户刷新提交POST请求导致重复提交。 2)用户点击返回按钮返回数据提交界面,导致重复提交数据。 3)用户多次点击提交按钮,导致重复提交数据。 4)用户恶意避开客户端阻止多次提交的手段,重复提交数据。4.使用session和annotation设置token。所谓token其实就是一种标识,标识当前的提交状态。比如古代皇帝下命令的时候,都会给属下一个虎符让手下随身携带给将军转达,而将军手上也有皇帝赐予的虎符的另一半.将军比较了一下,发现可以搭成一对,便按照传来的命令前去应战。若是来人身上没有虎符,将军必斩之。那么这个令牌呢?设置,下图是写这个token令牌的思路:1.先写一个简单的注解类importjava.lang.annotation.Documented;importjava.lang.annotation.ElementType;importjava.lang.annotation.Retention;importjava.lang.annotation.RetentionPolicy;importjava.lang.annotation.Target;/**自定义一个Token注解标识需要防止重投的方法@authorranger**/@Target(value=ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic@interfaceTokenForm{//用于标记需要反保留方法,创建Token属性booleancreate()defaultfalse;//用于标记需要反保留方法,删除属性ofTokenbooleanremove()defaultfalse;}2.跳转添加页面前,创建token/***跳转添加页面*请求路径:${pageContext.request.contextPath}/admin/toAdminAdd*@return*/@RequestMapping(value="/toAdminAdd")@TokenForm(create=true)publicStringtoAdminAdd(HttpServletRequestrequest){return"manager/adminAdd";}3.添加数据后删除token/***添加管理成员*请求路径:${pageContext.request.contextPath}/admin/addAdmin*@paramadmin*@paramrequest*@return*/@RequestMapping(value="/addAdmin")@TokenForm(remove=true)publicStringaddAdmin(@RequestParamMapadmin,HttpServletRequestrequest){try{//将密码Md5编码后插入admin.put("admin_pwd",Md5Utils.md5((String)admin.get("admin_pwd")));LOGGER.debug("-添加管理员-"+admin);adminService.addAdmin(admin);request.setAttribute("admin_add_msg","添加管理员成功");}catch(Exceptione){e.printStackTrace();request.setAttribute("admin_add_msg","添加管理员失败");}返回“经理/adminAdd”;}4。创建一个拦截器,在发送路径之前拦截token信息servlet.http.HttpServletResponse;导入javax.servlet.http.HttpSession;导入org.apache.log4j.LogManager;导入org.apache.log4j.Logger;导入org.springframework.web.method.HandlerMethod;导入org.springframework.web.servlet.HandlerInterceptor;importorg.springframework.web.servlet.ModelAndView;importcn.gzsxt.annotation.TokenForm;publicclassTokenInterceptorimplementsHandlerInterceptor{privatestaticfinalLoggerLOGGER=LogManager.getLogger(TokenInterceptor.class);request,HttpServletResponseresponse,Objecthandler)throwsException{//第一步:获取调用处理方法HandlerMethod的注解hm=(HandlerMethod)handler;TokenFormtokenForm=hm.getMethodAnnotation(TokenForm.class);//第二步:判断是否有Token注解if(tokenForm!=null){HttpSessionsession=request.getSession();如果(tokenForm.create()==true){session.setAttribute("token",UUID.randomUUID().toString());LOGGER.debug("打印的令牌:"+session.getAttribute("token"));}if(tokenForm.remove()==true){//判断表单的Token与serverString的Token是否相同StringformToken=request.getParameter("令牌");ObjectsessionToken=session.getAttribute("token");//传入的Token与服务端的Token相同,允许操作并删除会话Tokenif(formToken.equals(sessionToken)){session.removeAttribute("token");}else{//跳转到指定路径Stringinvoke=request.getParameter("token.invoke");response.sendRedirect(request.getContextPath()+调用);返回假;}}}returntrue;}@OverridepublicvoidpostHandle(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler,ModelAndViewmodelAndView)throwsException{//TODO自动生成的方法存根}@OverridepublicvoidafterCompletion(HttpServletRequestrequest,HttpServletResponseresponse,Objecthandler,Exceptionex)throwsException{//TODOAuto-generatedmethodstub}5.前端提交的token和重复提交后可以重定向的地址token.invoke