用户提交表单时可能因为网速的原因,或者网页被恶意刷新,多次点击submit提交,提交后刷新浏览器,浏览器URL回车致使表单重复提交,后果可想而知。这种情况我们可以从前端控制,也可以从后端。
从前端控制的话有多种方式:
1、设置点击后不可操作时间
var clickTimeOut = true; $(".btn").click(function(e){ if(!clickTimeOut)return; setTimeout(function(){clickTimeOut = true;},1000); clickTimeOut = false; })
3、提交后重定向到另一个信息页面
从后台控制:
使用Struts2方式,如下:
1、改变result的type类型为redirect
struts2的默认result类型为dispatcher,当用户将信息提交到服务器,服务器响应采用forward方式调转到下一个页面后,此时地址栏中显示的是上个页面的URL,若刷新当前页面,浏览器会将再次提交用户先前输入的数据,就会再次出现表单重复提交的问题。如果选择redirect方式跳转页面,这样就不会出现重复提交的问题;
缺点:redirect跳转无法满足开发过程中的一些需求。
2、采用标签方式 <s:token />
<form id="login_form" method="post" action="userAction!login"> <s:token></s:token> 用 户<input type="text" name="username" placeholder="输入用户" /> 密 码<input type="password" name="password" placeholder="输入密码" /> <div id="btn"> <a id="loginbutton" href="javascript:void(0)" onclick="login_submit()">登录</a> <a href="javascript:void(0)" onclick="login_reset()">清空</a> </div> </form>
<action name="userAction" class="com.yingjun.sharing.action.UserAction" > <interceptor-ref name="myStack" /> <interceptor-ref name="token" /> <result name="invalid.token">/WEB-INF/jsp/login.jsp</result> <result name="input">/WEB-INF/jsp/register.jsp</result> <result name="regsuccess">/WEB-INF/jsp/login.jsp</result> </action>
<action name="userAction" class="com.yingjun.sharing.action.UserAction" > <interceptor-ref name="tokenSession" > <param name="includeMethods">register</param> </interceptor-ref> <interceptor-ref name="myStack"/> <result name="input">/WEB-INF/jsp/register.jsp</result> <result name="regsuccess">/WEB-INF/jsp/login.jsp</result> </action>把token拦截器换为tokenSession拦截器。tokenSession拦截器与token拦截器唯一的不同是在判断某个请求为重复请求之后,并不是立即重定向到名为invalid.token的Result,而是先阻塞这个重复请求,直到浏览器响应最初的正常请求,然后就可以跳转到处理正常请求后的Result了。
注意:当浏览器URL回车的时候,使用tokenSession,又没有配置<result name="invalid.token">的时候会出现404
该原理就是在页面加载时,<s: token />产生一个GUID(Globally Unique Identifier,全局唯一标识符)值的隐藏输入框如:
<input type="hidden" name="struts.token.name" value="struts.token"/>
<input type="hidden" name="struts.token" value="BXPNNDG6BB11ZXHPI4E106CZ5K7VNMHR"/>
同时,将GUID放到会话(session)中;在执行action之前,“token”拦截器将会话token与请求token比较,如果两者相同,则将会话中的token删除并往下执行,否则向actionErrors加入错误信息。如此一来,如果用户通过某种手段提交了两次相同的请求,两个token就会不同。
知道了原理后我们也可以手工从后台处理,在session存放一个特殊标识,当表单页面被请求时,生成一个特殊的字符标志串,存在session中,同时放在表单的隐藏域里。接受处理表单数据时,检查标识字串是否存在,并立即从session中删除它,然后正常处理数据。如果发现表单提交里没有有效的标志串,这说明表单已经被提交过了,忽略这次提交。
整理自网络
原文:http://blog.csdn.net/hz_blog/article/details/24140801