1.造成表单重复提交原因
a.由于服务器处理延迟缘故,人为缘故再次提交.
b.由Forward(转发)跳转引起重复提交.当用户将信息提交到服务器时,服务器想响应采用的forward方式跳转到下一个页面,但是此时浏览器的地址栏不会更改(依旧显示的上一个页面的地址)如果刷新当前页面,会造成表单的再一次的提交.(如果采用redirect"重定向"方式进行跳转页面,就不会出现这种情况的表单重复提交问题,但有时为了达到某种效果,或出于网站安全的目的需要隐藏网页跳转,就需要采用forward"转发"方式).
2.struts2中的token和tokenSession运作原理
1).当用户首次访问表单页面时,服务器会在这次会话中创建一个session对象,并产生一个令牌值(token),然后将这个令牌值作为隐藏域的值,随表单一起发送到服务器端,同时将令牌值保存到session对象中.
2).在用户提交页面时,服务器首先判断请求请求参数中的令牌值和session对象中的令牌值是否相等,若相等,则清除session的令牌值,然后执行数据操作.如果不相等,则提示用户已经提交过了表单,同时产生一个新的令牌值,保存到session中,当用户重新访问提交数据页面时,将新产生的令牌值作为隐藏域的值.
3.运用
1).在struts.xml
<?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> <!-- 默认的视图主题 --> <constant name="struts.ui.theme" value="simple" /> <!-- struts2在防止表单重复提交的拦截中有2个,分别是:token,tokenSession.tokenSession继承token而来. 通常情况下,使用tokenSession客户端感觉会比较友好。 --> <!-- 如果重复提交,会跳转到error.jsp页面 . --> <package name="person" namespace="/test" extends="struts-default"> <action name="token" class="org.oolin.action.PersonAction"> <interceptor-ref name="defaultStack" /> <interceptor-ref name="token" /> <!-- 如果重复提交,跳转到error.jsp页面 --> <result name="invalid.token">/WEB-INF/page/error.jsp</result> <result>/WEB-INF/page/message.jsp</result> </action> <action name="tokenSession" class="org.oolin.action.PersonAction"> <interceptor-ref name="defaultStack"/> <interceptor-ref name="tokenSession"/> <!-- 如果重复提交,不会跳转到error.jsp页面 --> <result name='invalid.token'>?WEB-INF/page.jsp</result> <result>/WEB-INF/page/message.jsp</result> </action> </package> </struts>
ps:其中token和tokenSession任意一个都行.
2).表单页面index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@taglib uri="/struts-tags" prefix="s" %> <% String path = request.getContextPath(); String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/"; %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <base href="<%=basePath%>"> <title>防止表单重复提交</title> <meta http-equiv="pragma" content="no-cache"> <meta http-equiv="cache-control" content="no-cache"> <meta http-equiv="expires" content="0"> <meta http-equiv="keywords" content="keyword1,keyword2,keyword3"> <meta http-equiv="description" content="This is my page"> </head> <body> <!-- 防止表单重复提交,记得在form表单里填上<s:token></s:token> --> <s:form action="token" namespace="/test" method="post"> name:<s:textfield name="name" /> <s:token></s:token> <input type="submit" value="发送"/> </s:form> </body> </html>
ps:还有一种在浏览器端的防止表单重复提交,属于js的工作范畴,稍后提供.