先了解下为什么会有重复提交问题:
重复提交说白了就是重复操作了相同的记录,导致内存中有多条相同的记录的情况。
1、 在表单提交到一个action,而action又通过请求转发dispatcher(forward)的方式响应了一个JSP(HTML)页面, 此时地址栏还保留着action的那个路径,在响应页面点击“刷新”,这就是一个重复提交的情况。
2、在响应页面没有到达时,重复点击提交按钮。即我们所说的网络阻塞情况下。
3、点击返回,再点击提交。例如:登陆成功后,后退后再登陆。
处理表单重复提交有2中方法:客户端处理和服务端处理:
客户端处理:(用js定义一个全局的变量来控制表单不提交)
定义一个js:
<script language="javascript">
var checkSubmitFlg = false;
function checkSubmit() {
if (checkSubmitFlg == true) {
return false;
}
checkSubmitFlg = true;
return true;
}
</script>
总结:处理表单重复提交的方法
<s:form name="userForm" method="post" action="user/add_user" onSubmit="return checkSubmit();">
服务端处理(令牌机制)
介绍下struts2提供了一种Session级别的令牌机制Token
原理:
1.在regist.jsp页面使用<s: token />中生成一个唯一随机值,当用户访问此表单的网页时,就将其保存到Session中, 同时将其保存为表单的隐藏域的值.
2.在处理注册的请求时,获取Session中值,获取请求参数的值,比较两者是否相同, 如果相同说明不是重复提交,请求通过同时删除session中保存的值, 如果不相同则是重复提交, 不能通过.
这里我就介绍下用token来防止:
<div style="color: rgb(51, 51, 51); text-align: left;"><span style="font-family: 'Microsoft Yahei', 微软雅黑, arial, 宋体, sans-serif;"> <s:form name="loginForm" method="post" action="login"</span></div><div style="color: rgb(51, 51, 51); text-align: left;"> theme="simple"></div><span style="color:#333333;"> <tr>
</span><div style="color: rgb(51, 51, 51); text-align: left;"><span style="font-family: 'Microsoft Yahei', 微软雅黑, arial, 宋体, sans-serif;"> <td width="30" height="31"><input name="user.userName"</span></div><span style="color:#333333;"> <td width="70" height="31" align="center">用户名:</td>
</span><div style="color: rgb(51, 51, 51); text-align: left;"><span style="font-family: 'Microsoft Yahei', 微软雅黑, arial, 宋体, sans-serif;"> <td width="20" height="31" align="right"><s:fielderror</span></div><span style="color:#333333;"> type="text" class="input"></td>
fieldName="userName"></s:fielderror></td>
</span><div style="color: rgb(51, 51, 51); text-align: left;"><span style="font-family: 'Microsoft Yahei', 微软雅黑, arial, 宋体, sans-serif;"> <td width="30" height="29"><input name="user.passWord"</span></div><span style="color:#333333;"> </tr>
<tr>
<td width="70" height="29" align="center">密 码:</td>
</span><div style="color: rgb(51, 51, 51); text-align: left;"><span style="font-family: 'Microsoft Yahei', 微软雅黑, arial, 宋体, sans-serif;"> <td width="20" height="31" align="right"><s:fielderror</span></div><span style="color:#333333;"> type="password" class="input">
</td>
fieldName="password"></s:fielderror></td>
</tr>
</span><div style="color: rgb(51, 51, 51); text-align: left;"><span style="font-family: 'Microsoft Yahei', 微软雅黑, arial, 宋体, sans-serif;"> type="submit" name="Submit" value="登陆" class="button"></span></div><span style="color:#333333;"> <tr>
<td height="30" colspan="2" align="center"><input
<input type="reset" name="Submit2" value="重置"
</span><div style="text-align: left;"><span style="font-family: 'Microsoft Yahei', 微软雅黑, arial, 宋体, sans-serif;"><span style="color:#333333;"> </span><span style="color:#ff0000;"><s:token /></span></span></div><span style="color:#333333;"> class="button">
</td>
</span><div style="color: rgb(51, 51, 51); text-align: left;"><span style="font-family: 'Microsoft Yahei', 微软雅黑, arial, 宋体, sans-serif;"> </tr></span></div>
<span style="white-space:pre"> </span><interceptors>
<interceptor-stack name="tokenStack">
<interceptor-ref name="token" />
<interceptor-ref name="defaultStack" />
</interceptor-stack>
</interceptors>
在需要拦截的action中配置该拦截器:
<span style="color: rgb(51, 51, 51); white-space: pre;"> </span><span style="color:#333333;"><action name="login" class="loginAction" method="login">
<interceptor-ref name="tokenStack"></interceptor-ref>
</span><span style="color:#ff0000;"><result name="invalid.token">/WEB-INF/error/error.jsp</result></span><span style="color:#333333;">
<!-- 这里用redirect防止在刷新时造成重复提交表单的问题 -->
<result name="login_success" type="redirectAction">empty/manage_empty</result>
<result name="input" type="redirect">/index.jsp</result>
</action></span>
ps:
以前说重定向可以解决表单重复提交的问题,但这只能防止用户点击刷新按钮,如果用redirect,url会改变,也就没有重复提交的问题,但是当我点击浏览器中的返回,然后再点击提交,如此反复,仍然在重复调用action,这也是重复提交,这时就要用token防止了。
总结:如果使用客户端处理,则重复提交不上去,页面也不会跳转。
如果用服务端处理,需要定义一个重复提交的页面,这样做的好处是可以自己处理重复提交的业务逻辑。
总之,仁者见仁智者见智……