Java中避免表单重复提交
表单的重复提交: 没有完整的进行一次,先请求表单页面->再提交表单过程而完成数据提交
造成的根本原因: 没有完整的进行一次,先请求表单页面->再提交表单过程.
造成重复提交的现象:
- 由于服务器缓慢或网络延迟的原因,重复点击提交按钮.
- 已经提交成功,刷新成功页面(forward)(请求转发).
- 已经提交成功,通过回退,再次点击提交按钮
- 注意:回退后,刷新表单页面,重新再提交,这时,不是重复提交,而是发送新的请求,在Firefox下,重复提交到同一个地址的操作无效.
案例:
@WebServlet("/trans")
public class TransferServlet extends HttpServlet{
private static final long serialVersionUID = 1L; protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
PrintWriter out = resp.getWriter();
String money = req.getParameter("money");
//通过睡眠,模拟网络延迟
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("转出金额:"+money);
out.print("转出金额:"+money);
}
}
在狂点之下,会发现,jsp页面不会有变化,但是通过后台的打印输出可以看到,会不停地输出,说明一直在执行
解决方法:
保证提交保证之前,就必须先请求表单界面,原理和验证码一样.----令牌机制
在第一次请求的时候,请求到表单界面时,创建一个令牌,当点击转账,发送请求的时候,带上这个令牌,发送到下一个界面,在servlet中对这个令牌进行验证,这个令牌在session中一份,在表单中一份,相等说明表单正确,并且把这个session中的令牌销毁掉.
在jsp页面中的代码
<%
//创建令牌
String token = java.util.UUID.randomUUID().toString();
//存在session中一份,以后做判断
session.setAttribute("TOKEN_IN_SESSION", token);
%> <h3>转账界面</h3>
<form action="/trans" method="post">
<input type="hidden" name="token" value="<%=token%>"/>
转账金额:<input type="text" name="money" min="1" required /><br/>
<input type="submit" value="转账" />
</form>
在TransferServlet中的代码
@WebServlet("/trans")
public class TransferServlet extends HttpServlet{
private static final long serialVersionUID = 1L; protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
req.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
PrintWriter out = resp.getWriter();
//获取表单中的token值
String token = req.getParameter("token");
//获取session中的token值
String sessionToken = (String) req.getSession().getAttribute("TOKEN_IN_SESSION");
//session中的token容易为空,因为session中的token是需要被销毁的 if (token.equals(sessionToken)) {
//说明令牌相同
req.getSession().removeAttribute("TOKEN_IN_SESSION");
String money = req.getParameter("money");
System.out.println("转出金额:"+money);
out.print("转出金额:"+money);
//最后销毁session中的令牌
}
//如果令牌不同说明就是重复提交,不能提交
}
}
然后呢,为了不想在jsp文件中出现Java代码,把令牌的创建并跳转放在另一个servlet中
@WebServlet("/transfer")
public class CopyOfTransferServlet extends HttpServlet{
private static final long serialVersionUID = 1L; protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//创建令牌,并跳转到submit.jsp
String token = UUID.randomUUID().toString();
System.out.println(token);
req.getSession().setAttribute("TOKEN_IN_SESSION", token);
req.setAttribute("token", token);
req.getRequestDispatcher("/views/repeatsubmit/submit.jsp").forward(req, resp); }
}
此时jsp文件中就是这个样子
<h3>转账界面</h3>
<form action="/trans" method="post">
<input type="hidden" name="token" value="${token }"/>
转账金额:<input type="text" name="money" min="1" required /><br/>
<input type="submit" value="转账" />
</form>
比上面的干净了很多,更加整齐,但是还是感觉不好,因为如果在其他地方需要用到,还需要在创建令牌,校验令牌,删除令牌,因此就抽取出来做一个工具类
TokenUtil.java
1 //令牌的工具类
//创建令牌
//校验令牌
//销毁令牌
public class TokenUtil {
private final static String TOKEN_IN_SESSION = "TOKEN_IN_SESSION";
public static void savaToken(HttpServletRequest req) {
String token = UUID.randomUUID().toString();
System.out.println(token);
req.getSession().setAttribute(TOKEN_IN_SESSION, token);
req.setAttribute("token", token);
} public static boolean validateToken(HttpServletRequest req,
String tokenInrequest) {
//获取session中的token值
String sessionToken = (String) req.getSession().getAttribute(
TOKEN_IN_SESSION);
if (tokenInrequest.equals(sessionToken)) {
req.getSession().removeAttribute(TOKEN_IN_SESSION);
return true;
}
return false;
}
}
这样就好了,使用者只需要调用这个工具类就好了,不需要再去写创建令牌等一系列操作
Java中避免表单重复提交的更多相关文章
- java web解决表单重复提交问题
我们大家再进行web开发的时候,必不可少会遇见表单重复提交问题.今天就来给总结如何解决表单提交问题,欢迎大家交流指正. 首先我们在讨论如何解决表单重复提交问题之前先来解决三个问题:1.什么叫表单重复提 ...
- 使用js控制表单重复提交(1加锁,2事件方式,3 EasyUI中解决表单重复提交)
方法一. var flag = true; $(function() { $("#interested").click(function() { beInterested(); } ...
- java web解决表单重复提交
首先我们在讨论如何解决表单重复提交问题之前先来解决三个问题:1.什么叫表单重复提交?2.什么情况下会出现表单重复提交?3.什么情况需要避免表单重复提交? 什么叫表单提交问题,说白了,就是同一份信息,重 ...
- [原创]java WEB学习笔记73:Struts2 学习之路-- strut2中防止表单重复提交
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- Java Web之表单重复提交问题
上篇文章讲了验证码的制作,提及到了一个问题,就是表单重复提交的问题,可能在上次那个验证码中感觉不是那么的重要 现在我新写一个例子,转钱.通过这个例子你就知道表单重复提交有多恐怖了. 先来简单的介绍一下 ...
- Struts2中解决表单重复提交
3. 表单的重复提交问题 1). 什么是表单的重复提交 > 在不刷新表单页面的前提下: >> 多次点击提交按钮 >> 已经提交成功, 按 "回退" ...
- Struts2中防止表单重复提交,global-results定义全局结果处理
1.在表单中加入<s:token/>标签 2.在动作类中加入token的拦截器 <!--如果单单写 name="token" 会丧失 defaultStack 拦 ...
- Struts(二十七):使用token或tokenSession防止表单重复提交
什么是表单重复提交 表单重复提交包括以下几种情况: 前提:不刷新表单页面 1.多次点击“提交”按钮后,重复提交了多次: 2.已经提交成功之后,按“回退”按钮之后,在点击“提交”按钮后,提交成功: 3. ...
- 【Struts2】防止表单重复提交
一.概述 二.Struts2中解决方案 三.实现步骤 一.概述 regist.jsp----->RegistServlet 表单重复提交 危害: 刷票. 重复注册.带来服务器访问压力(拒绝服务) ...
随机推荐
- Unity3D 一个较常见的错误信息“rect[2] == rt->GetGLWidth() && rect[3] == rt->GetGLHeight()”
rect[2] == rt->GetGLWidth() && rect[3] == rt->GetGLHeight() 这个错误信息的具体含义我还不太清楚.它出现以后会不停 ...
- 【转】sql to_char 日期转换字符串
1.转换函数 与date操作关系最大的就是两个转换函数:to_date(),to_char() to_date() 作用将字符类型按一定格式转化为日期类型: 具体用法:to_date('2004-11 ...
- beego 框架入门
根据官网向导安装配置好环境和工具https://beego.me 就可以开始了,先来入门下. 1.新建项目 在项目目录下 bee new quickstart成功后就可以运行了 http serve ...
- Extjs,Git,插件....学习网址
详细的extjs讲解http://wenku.baidu.com/view/e98a781352d380eb62946de4.html 博客 http://www.cnblogs.com/iamlil ...
- google软件测试之道--读后笔记
看完google软件测试之道,以前有认真看过一次,今天又重新看了一遍. 在google,测试人员严格区分为SET和TE.SET前期深度参与项目的开发,推动开发人员的自测,从破坏者的角度寻 ...
- NSOperationQueue的其他方法
1.设置最大并发数 什么是并发数 同时执行的任务数 比如,同时开3个线程执行3个任务,并发数就是3 最大并发数的相关方法 - (NSInteger)maxConcurrentOperationCo ...
- software_testing_work2_question1(改)_edition
由于上个版本问题多多,而且测试情况略有呵呵,于是想想还是默默的改进了一个版本. input类 首先呢,是作为输入项的实体类input. 对比之前的版本,新版本(姑且称其为edition2)加强了ope ...
- 关于peersim样例配置文件的超详细解读(新手勿喷)
相信很多兄弟一开始接触peersim,对配置文件还是有点不适应,我看了好久的样例的配置文件,一层层去找对应的文件的方法,终于好像悟懂了一点,记下来以后回顾. 贴上代码,一点点分析. 首先要说下所谓的配 ...
- gulp(一)
简介: gulp是前端开发过程中对代码进行构建的工具,是自动化项目的构建利器:她不仅能对网站资源进行优化,而且在开发过程中很多重复的任务能够使用正确的工具自动完成:使用她,我们不仅可以很愉快的编写代码 ...
- Autorun.inf文件(2):改变硬盘分区图标
改变F盘图标. 原理:在f盘下新建一个Autorun.inf文件,文件内容是 [AutoRun]icon=favicon.ico准备名为favicon.ico图标文件,将其放在工程目录里,设计程序将它 ...