1.什么是重复提交
在不刷新表单页面的情况下
- 》多次点击提交按钮
- 》已经提交成功了,按“回退”之后,再点击"提交按钮"
- 》在控制器相应页面的形式为转发的情况下,已经提交成功,然后点击刷新或者f5
注意:
- 》若刷新表单页面,再提交表单就不是重复提交
- 》若使用redirect的相应类型,已经提交成功之后,再点击"刷新",不算是重复提交
表单重复提交的危害
-
增加服务器的负担
-
导致程序错误
解决的方式:Token拦截器或者TokenSession拦截
一、在s:form中添加一个子标签s:token
- 这个子标签会生成一个隐藏域
- 在session添加一个属性值
隐藏域和session的属性值一致就提交成功
二 使用Token或TokenSession拦截器
》这两个拦截器均不在默认的拦截器栈中,所以需要手工配置一下
》若使用Token拦截器,则需要配置token.valid的result
》若使用TokenStack拦截器,则不需要为他配置任何其他的result
三、Token vs TokenStack
》都是解决表单重复提交问题的
》使用token拦截器,则需要配置一个token.valid的result
》若使用TokenSession拦截器,则还会响应那个目标页面,但是不会执行tockenSession之后的拦截器,跟什么也没有发生一样
四、可以使用s:actionerror标签来显示重复提交的错误消息
该错误消息可以在国际资源文件中覆盖,该消息可以在struts-messages.properties文件中找到
demo如下
jsp表单页面
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%
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>
<s:form action="texttoken">
<s:token></s:token>
<s:textfield label="name" name="username"></s:textfield>
<s:submit></s:submit>
</s:form>
</body>
</html>
struts.xml
<action name="texttoken" class="cn.com.app.TextToken">
<interceptor-ref name="token"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
<result>/success.jsp</result>
<result name="invalid.token">/error.jsp</result>
</action>
Action类
package cn.com.app;
import com.opensymphony.xwork2.ActionSupport;
public class TextToken extends ActionSupport {
private String username;
public void setUsername(String username) {
this.username = username;
}
public String getUsername() {
return username;
}
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
System.out.println(username);
return super.execute();
}
}
错误信息页面
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%
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>
<s:actionerror/>
</body>
</html>
当我们在前台页上输入一个名字的时候,点击提交到了提交成功的页面,点击刷新,就会出现报错页面、显示错误信息
如果使用的是tokenSession拦截器的话,就如下操作就可以了
<action name="texttoken" class="cn.com.app.TextToken">
<interceptor-ref name="tokenSession"></interceptor-ref>
<interceptor-ref name="defaultStack"></interceptor-ref>
<result>/success.jsp</result>
<!-- <result name="invalid.token">/error.jsp</result> -->
</action>
页面也不会打印错误信息,就跟什么也没有发生一样