Form表单重复提交是web开发中一个很常见的问题。先总结以下几种解决方案
模拟Action后台查询数据需要时间等待,此间用户可能会多次点击提交按钮或者刷新页面,此时Action也会反复执行多次,这并不是我们想要的。如下,模拟Action操作。
TestAction.java
public class TestAction { private User user;//省略get/set方法... public String execute() { try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("-------------业务处理-------------"); System.out.println("user.username--->" + user.getUsername()); System.out.println("user.age--->" + user.getAge()); return "test"; } }
struts.xml
<action name="test" class="com.lydia.web.action.TestAction" > <result name="test">/ognl.jsp</result> <action>
解决方案1:利用javascript脚步
index.jsp
<%@ page language="java" import="java.util.*" contentType="text/html; charset=UTF-8"%> <html> <head> <script type="text/javascript" language="javascript"> var isSubmitFlag = false; function checkSubmit(){ if(!isSubmitFlag){ isSubmitFlag = true; return true; }else{ alert("不能重复提交"); return false; } } </script> </head> <body> This is my JSP page. <br> <form name="form" action="test" method="post" onsubmit="return checkSubmit();"> username : <input name="user.username" /> <br/> age : <input name="user.age " /><br/> <span id="t" style="color: red"></span> <input type="submit" value="提交" id="sub"/> </form> </body> </html>
此种方法通过设置 onsubmit="return false" 来防止表单提交,类似的还可以在第一次提交后把提交按钮设置为不可用;或者显示正在提交中等。
function checkSubmit(){ document.getElementById("tt").innerHTML="提交中..."; document.getElementById("btu").disabled="disabled"; return true; }
解决方案2:struts2的token令牌机制
这种做法非常简单,步骤如下
1)在jsp页面的表单中添加<s:token></s:token>标签。
2)修改struts.xml
a,如果需要错误页面提示,点击多次也只提交一次,但是会跳转到错误页面提示表单重复提交了:
使用token
<action name="test" class="com.tarena.web.action.TestAction" > <result type="dispatcher" name="test">/ognl.jsp</result> <result type="redirect" name="index">/index.jsp</result> <result name="invalid.token">/error.jsp?message=重复提交</result> <interceptor-ref name="token"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </action>
b,不需要错误页面提示,即使点击多次也只提交一次。 使用tokenSession
<action name="test" class="com.tarena.web.action.TestAction" > <result type="dispatcher" name="test">/ognl.jsp</result> <result type="redirect" name="index">/index.jsp</result> <interceptor-ref name="tokenSession"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </action>
注意:
a:当拦截器拦截到 当发生重复提交的action时候,会跳转到invalid.token指定的页面。
b:为了使用同一的错误页面,在错误页面上接受到message参数的值,可以在error.jsp使用${param['message']}
c:在提交页面的form中添加<s:token/>标签,需要在页面中加上
token的工作原理。我们会发现使用<s:token></s:token>后,jsp页面中会多出:
<input type="hidden" name="struts.token.name" value="struts.token" />
<input type="hidden" name="struts.token" value="HZC4XCH5K9Q3KEXR0D4HZKJI8PYOSAOJ" />
当页面提交的时候时候他会判断这个值是不是和session的一样,如果是一样的,你可以提交,并且会修改session里的值。如果你刷新或重复提交,那你页面上的值和session的值就不一样的,struts就不允许你提交数据了。就是这个原理。