用户重复提交表单在某些场合将会形成很是严重的后果。例如,在使用信用卡进行在线支付的时候,若是服务器的响应速度太慢,用户有可能会屡次点击提交按钮,而这可能致使那张信用卡上的金额被消费了屡次。所以,重复提交表单会对你的系统带来逻辑影响,必须采起一些措施防止这类状况的发生。apache
用户重复提交同一个HTML表单的缘由有: 1、快速屡次点击了提交按钮;2、提交表单后按下浏览器的刷新按钮。浏览器
设置Struts 2的预防表单重复提交的功能 服务器
Struts 2已经内置了可以防止用户重复提交同一个HTML表单的功能。它的工做原理:让服务器生成一个惟一标记,并在服务器和表单里各保存一份这个标记的副本。此后,在用户提交表单的时候,表单里的标记将随着其余请求参数一块儿发送到服务器,服务器将对他收到的标记和它留存的标记进行比较。若是二者匹配,此次提交的表单被认为是有效的,服务器将对之作出必要的处理并从新设置一个新标记。随后,提交相同的表单就会失败,由于服务器上的标记已经重置。 jsp
Struts 2标签中的token标签,能够用来生成一个独一无二的标记。这个标记必须嵌套在form标签中使用,它会在表单里插入一个隐藏字段并把标记保存到HttpSession对象里。toke标签必须与Token或Token Session拦截器配合使用,两个拦截器都能对token标签进行处理。Token拦截器遇到重复提交表单的状况,会返回一个"invalid.token"结果并加上一个动做级别的错误。Token Session拦截器扩展了Token拦截器并提供了一种更复杂的服务,它采起的作法与Token拦截器不一样,它只是阻断了后续的提交,这样用户不提交多少次,就好像只是提交了一次。 ide
示例:使用Token拦截器预防表单重复提交测试
1. 配置struts.xml文件,声明动做this
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <package name="avoidPackage" extends="struts-default"> <action name="avoid" class="struts2.action.AvoidAction"> <interceptor-ref name="token"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> <result name="invalid.token">/error.jsp</result> <result name="input">/input.jsp</result> <result name="success">/output.jsp</result> </action> </package> </struts>
此时,须要在动做的声明中,为动做添加token拦截器,由于token拦截器不在defaultStack拦截器栈中,注意,须要将拦截器放在拦截器栈的第一位,这是由于判断表单是否被重复提交的逻辑应该在表单处理前。spa
2. 建立动做类orm
public class AvoidAction extends ActionSupport { private static final long serialVersionUID = 2676453800249807631L; private String username; private Date birthday; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } @Override public String execute() { try { Thread.sleep(4000); } catch (InterruptedException e) { e.printStackTrace(); } return SUCCESS; } }
这个动做逻辑处理为挂起4秒钟,让咱们有机会屡次点击提交按钮,测试效果。xml
3. 建立页面:
input.jsp
<s:form action="avoid"> <s:token></s:token> <s:textfield name="username" label="Enter your name"></s:textfield> <s:textfield name="birthday" label="Enter your birthday"></s:textfield> <s:submit value="submit"></s:submit> </s:form>
要使用Struts 2的防止表单重复提交功能,须要在form标签中使用token标签,他会产生一个惟一的标识符,与其余参数一块儿提交到服务器,服务器会根据token标签所产生的标识符判断表单是否为重复提交的表单,这个功能是由Token拦截器完成的。
error.jsp
<body> do not duplicate submissions form! </body>
当表单重复提交,Token拦截器会返回一个"invalid.token"结果,结果将页面转到这个页面,提示用户错误信息。
output.jsp
<body> Your Name : <s:property value="username"/> <br /> Your Birthday : <s:property value="birthday"/> </body>
若没有重复提交表单,那么就显示正确的页面。
4. 测试
在浏览器中输入:http://localhost:8081/AvoidDuplicateSubmissions/input.jsp,获得以下界面
连续屡次点击"submit"按钮,查看效果
能够看到,token拦截器的设置生效了,他阻止了表单的重复提交,并给出了错误提示
此次咱们只点击一次提交(请从新输入URL,或后退到输入页面后刷新一下,这是由于token的标示在提交一次后已被修改,不刷新标示符是不可能与服务器存留的标示符一致的)
能够看到,表单被正确的处理了。
处理表单重复提交的另外一个拦截器是 tokenSession,使用该拦截器与使用token拦截器并无什么差别只须要,引用该拦截器,其余与token拦截器彻底一致
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.0.dtd"> <struts> <package name="avoidPackage" extends="struts-default"> <action name="avoid" class="struts2.action.AvoidAction"> <interceptor-ref name="tokenSession"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> <result name="invalid.token">/error.jsp</result> <result name="input">/input.jsp</result> <result name="success">/output.jsp</result> </action> </package> </struts>