Struts2 - 表单的重复提交问题
用户重复提交表单在某些场合将会造成非常严重的后果。例如,在使用信用卡进行在线支付的时候,如果服务器的响应速度太慢,用户有可能会多次点击提交按钮,而这可能导致那张信用卡上的金额被消费了多次。因此,重复提交表单会对你的系统带来逻辑影响,必须采取一些措施防止这类情况的发生。
用户重复提交同一个HTML表单的原因有: 一、快速多次点击了提交按钮;二、提交表单后按下浏览器的刷新按钮。
设置Struts 2的预防表单重复提交的功能
Struts 2已经内置了能够防止用户重复提交同一个HTML表单的功能。它的工作原理:让服务器生成一个唯一标记,并在服务器和表单里各保存一份这个标记的副本。此后,在用户提交表单的时候,表单里的标记将随着其他请求参数一起发送到服务器,服务器将对他收到的标记和它留存的标记进行比较。如果两者匹配,这次提交的表单被认为是有效的,服务器将对之做出必要的处理并重新设置一个新标记。随后,提交相同的表单就会失败,因为服务器上的标记已经重置。
Struts 2标签中的token标签,可以用来生成一个独一无二的标记。这个标记必须嵌套在form标签中使用,它会在表单里插入一个隐藏字段并把标记保存到HttpSession对象里。toke标签必须与Token或Token Session拦截器配合使用,两个拦截器都能对token标签进行处理。Token拦截器遇到重复提交表单的情况,会返回一个"invalid.token"结果并加上一个动作级别的错误。Token Session拦截器扩展了Token拦截器并提供了一种更复杂的服务,它采取的做法与Token拦截器不同,它只是阻断了后续的提交,这样用户不提交多少次,就好像只是提交了一次。
示例:使用Token拦截器预防表单重复提交
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>
<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拦截器栈中,注意,需要将拦截器放在拦截器栈的第一位,这是因为判断表单是否被重复提交的逻辑应该在表单处理前。
2. 创建动作类

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秒钟,让我们有机会多次点击提交按钮,测试效果。
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>

Struts2 - 表单的重复提交问题的更多相关文章
- struts2 文件的上传下载 表单的重复提交 自定义拦截器
文件上传中表单的准备 要想使用 HTML 表单上传一个或多个文件 须把 HTML 表单的 enctype 属性设置为 multipart/form-data 须把 HTML 表单的method 属性设 ...
- php中如何防止表单的重复提交
在php中如何防止表单的重复提交?其实也有几种解决方法. 下面小编就为大家介绍一下吧.需要的朋友可以过来参考下 代码: <?php /* * php中如何防止表单的重复提交 * by www.j ...
- php-- 避免表单的重复提交
用户提交表单时可能因为网速的原因,或者网页被恶意刷新,致使同一条记录重复插入到数据库中,这是一个比较棘手的问题.我们可以从客户端和服务器端一起着手,设法避免同一表单的重复提交. 1.使用客户端脚本 提 ...
- Spring MVC表单防重复提交
利用Spring MVC的过滤器及token传递验证来实现表单防重复提交. 创建注解 @Target(ElementType.METHOD) @Retention(RetentionPolicy.RU ...
- Session机制三(表单的重复提交)
1.表单的重复提交的情况 在表单提交到一个servlet,而servlet又通过请求转发的方式响应了一个JSP页面,这个时候地址栏还保留这servlet的那个路径,在响应页面点击刷新. 在响应页面没有 ...
- HttpSession解决表单的重复提交
1). 重复提交的情况: ①. 在表单提交到一个 Servlet, 而 Servlet 又通过请求转发的方式响应一个 JSP(HTML) 页面, 此时地址栏还保留着 Serlvet 的那个路径, 在响 ...
- 使用aop注解实现表单防重复提交功能
原文:https://www.cnblogs.com/manliu/articles/5983888.html 1.这里采用的方法是:使用get请求进入表单页面时,后台会生成一个tokrn_flag分 ...
- HttpSession之表单的重复提交 & 验证码
如果采用 HttpServletResponse.sendRedirct() 方法将客户端重定向到成功页面,将不会出现重复提交问题 1.表单的重复提交 1). 重复提交的情况: ①. 在表单提交到一个 ...
- struts2 防止表单的重复提交
防止表单重复提交(拦截器) 1.回顾之前的解决办法: 2.Struts2中的解决办法: 2.1.使用重定向 <result type="redirect">/succe ...
随机推荐
- EasyDSS流媒体解决方案实现的实时数据统计报表、视频文件上传、点播、分享、集成代码等功能
之前的EasyDSS作为rtmp流媒体服务器自从推出就备受用户好评,随着用户的需求的变更产品自身的发展是必须的: 为了更好的用户体验和和功能的完善,我们在EasyDSS的基础上增添了服务器硬件数据报表 ...
- C++模板类[初步]
/* * stacktp.h * * Created on: 2014年3月29日 * Author: */ /** * - 模板类的概念,与使用 * -# export template <c ...
- 九度OJ 1186:打印日期 (日期计算)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:6366 解决:2214 题目描述: 给出年分m和一年中的第n天,算出第n天是几月几号. 输入: 输入包括两个整数y(1<=y<= ...
- iOS 添加震动效果
开发过程中,有时候会碰到点击按钮或者某个动画会配合震动效果:下面介绍iOS开发过程中的震动添加: 导入:#import <AudioToolbox/AudioToolbox.h> 在需要出 ...
- 我的Android进阶之旅------>Android中android:visibility 属性VISIBLE、INVISIBLE、GONE的区别
在Android开发中,大部分控件都有visibility这个属性,其属性有3个分别为"visible "."invisible"."gone&quo ...
- 超轻量级、高性能C日志库--EasyLogger
[ 声明:版权全部,欢迎转载.请勿用于商业用途. 联系信箱:armink.ztl@gmail.com] EasyLogger 1. 介绍 EasyLogger 是一款超轻量级(ROM<1.6K, ...
- 忘记apple id如何更新应用?
最近ytkah的app有很多更新提示,之前注册的apple id好久没登录了,突然提示说登录需要验证安全问题,哪还记得噢,最要命的是邮箱收到的加密邮件也需要验证.重新注册一个吧,这次要注意保存相关信息 ...
- SAP号码段
[转http://blog.csdn.net/wengyupeng/article/details/8513527] 1.通用Tcode:SNRO 常用维护特定Number range Tcode: ...
- ABAP服务器文件操作
转自http://blog.itpub.net/547380/viewspace-876667/ 在程序设计开发过程中,很多要对文件进行操作,这又分为对本地文件操作和服务器文件操作.对本地文件操作使用 ...
- GCC 常用选项详解
参考gcc man page 参考:http://www.cppblog.com/seman/archive/2005/11/30/1440.html gcc and g++分别是gnu的c & ...