当用户填写完表单后,在提交过一次后,若用户做如下操作比如再次点击提交、刷新页面、提交页面呈现后点击后退按钮,都会导致表单重复提交。如果信息需要存储到后台数据库中,重复提交就会再次向数据库中插入用户信息,显然这样是不对的。解决方式有两种
(一)Session Token机制
当用户首次访问包含表单的页面时,此时服务器会做三件事
1)创建一个session对象,
2)通过解析<s:token>标签(编程时此标签在要加入表单页面中)会产生一个随机数(可以将其称为盾牌,注意这个不是session ID)保存在session中
3)服务器把产生的随机数发送给客户端
当用户向服务器提交表单的时候,此时服务器会做
1)判断从客户端发送过来的请求参数中的随机数和保存在session对象中随机数是否相等,如果相等,则认为是第一次提交。
2)若是第一次提交,服务器会把原来保存在session的随机数改变成其他的随机数。当时发送给客户端的随机数不变。
3)因为在第一次提交表单后,服务器端地随机数和客户端的不一样了,所以当重复提交的时候,服务器看到客户端的随机数和自己的不一样了就可以判断这是在重复提交了。
代码实现:
1、表单页面,注意:在使用session token时,必须用struts2表标签库
<%@taglib prefix="s" uri="/struts-tags" %>
register1.jsp页面
<s:form action="token" theme="simple"> username:<s:textfield name="username"></s:textfield><br/> password:<s:password name="password"></s:password><br/> <s:submit value="submit"></s:submit> <s:token></s:token> <!--服务器通过token标签 来产生盾牌随机数--> </s:form>
struts.xml
<action name="token" class="com.struts2.TokenAction"> <result name="success">/success.jsp</result> <result name="invalid.token">/invalid.jsp</result> <interceptor-ref name="token"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref> </action>
TokenAction
package com.struts2; import com.opensymphony.xwork2.ActionSupport; public class TokenAction extends ActionSupport { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String execute() throws Exception { return SUCCESS; } }
首次提交对应的success.jsp结果页面
<body> 注册成功! </body>
重复提交对应的invalid.jsp结果页面
1、在含有form表单的页面注意使用struts2表标签库
2、在含有form表单的页面加入<s:token></s:token> 标签
3、在struts.xml页面中配置:
<result name=”token.invalid”>/invalid.jsp</rssult> <interceptor-ref name="token"></interceptor-ref> <interceptor-ref name="defaultStack"></interceptor-ref>