上篇文章讲了验证码的制作,提及到了一个问题,就是表单重复提交的问题,可能在上次那个验证码中感觉不是那么的重要

现在我新写一个例子,转钱。通过这个例子你就知道表单重复提交有多恐怖了。

先来简单的介绍一下表单重复提交的3种现象

我们来一个个的实验,首先我们写两个东东,一个jsp,一个Servlet,jsp写了就不动了,Servlet会变化,我会在不同的现象下贴出代码

JSP:

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>转账</title>
</head>
<body>
<form action="/transform" method="post" >
转账金额:<input type="text" id="money" name="money" required> 元 <br>
<input type="submit" value="注册">
</form> </body>
</html>

Servlet我们会在不同的现象修改,下面直接看

1.服务器慢或者网络延迟,我们使用线程模拟一下

先看Servlet

package com.vae.RandomCode;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter; @WebServlet("/transform")
public class TransformServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=utf-8");
PrintWriter out=resp.getWriter();
String money=req.getParameter("money");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("转出:" + money);
out.println("转账成功");
}
}

运行,如图:

我点击注册,其实是转账。。。。

然后应该出现一大串的转账100,但是不知道怎么回事,我用线程模拟的情况并没有出现转账多次,所以这里暂时疑惑

2.已经提交成功,不小心刷新了页面

(Servlet代码删了线程就行了)

我们点击一次

然后我不小心的刷新了几次页面

卧槽???啥情况?我就是不小心刷新了几次,就要我多转出去钱???明显不合理

3.已经提交成功了,我回退,再次点击提交,我就是这么的事多.....

我点

我回退

我再点

。。。。。这种情况也是不行的。。。。虽然是用户自己作死。。。。。但是还是要规避一下。。。。

通过上面3个例子,我们知道了表单重复提交的恐怖,特别是涉及到钱的方面。所以我们要想个办法来规避这种情况,怎么办呢?

想想,我们是不是通过两次请求就可以实现转账了,一次是JSP的按钮点击,一次是Servlet的获取数据,那么我们只需要保证我们每次的操作,都有这两次请求就可以了

解决方案:令牌机制

我听到这个令牌机制就想起了狄仁杰...其实令牌机制就是一个随机数UUID,和我们的验证码里面的那个是一样的。其原理是

我在JSP页面点击按钮发出第一次请求的时候,就把我的令牌(随机数)保存到Session里面,并且把令牌传给Servlet,然后在Servlet里面判断两个是否相等

如果相等,就ok,转账,然后立马销毁session里面的令牌,这样无论你再怎么刷新,session里面已经没有令牌了,肯定不能转账了

话说到此,我们来看看最终的代码

JSP:

<%@ page import="java.util.UUID" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>转账</title>
</head>
<body> <%
//生成一个令牌
String token=UUID.randomUUID().toString();
//存放在session中
session.setAttribute("TOKEN_IN_SESSION",token);
%> <form action="/transform" method="post" >
<input type="hidden" name="token" value="<%=token%>"> <!--这个hidden是隐藏起来不可见-->
转账金额:<input type="text" id="money" name="money" required> 元 <br>
<input type="submit" value="注册">
</form> </body>
</html>

Servlet:

package com.vae.RandomCode;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter; @WebServlet("/transform")
public class TransformServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //表单中的令牌
String tokenInRequest=req.getParameter("token");
//session中的令牌
String tokenInSession=req.getSession().getAttribute("TOKEN_IN_SESSION").toString();
//比较
if (tokenInRequest.equals(tokenInSession)) {
//立马销毁session中的令牌再说
req.getSession().removeAttribute("TOKEN_IN_SESSION"); //然后干其他的事
resp.setContentType("text/html;charset=utf-8");
PrintWriter out=resp.getWriter();
String money=req.getParameter("money");
System.out.println("转出:" + money);
out.println("转账成功");
}else {
System.out.println("不让你转,重新去页面转吧");
} }
}

运行一下,结果已经ok了,我们使用了令牌机制(就是一个随机数)实现了避免表单的重复提交。

Java Web之表单重复提交问题的更多相关文章

  1. java web解决表单重复提交问题

    我们大家再进行web开发的时候,必不可少会遇见表单重复提交问题.今天就来给总结如何解决表单提交问题,欢迎大家交流指正. 首先我们在讨论如何解决表单重复提交问题之前先来解决三个问题:1.什么叫表单重复提 ...

  2. java web解决表单重复提交

    首先我们在讨论如何解决表单重复提交问题之前先来解决三个问题:1.什么叫表单重复提交?2.什么情况下会出现表单重复提交?3.什么情况需要避免表单重复提交? 什么叫表单提交问题,说白了,就是同一份信息,重 ...

  3. Java中避免表单重复提交

    表单的重复提交: 没有完整的进行一次,先请求表单页面->再提交表单过程而完成数据提交 造成的根本原因: 没有完整的进行一次,先请求表单页面->再提交表单过程. 造成重复提交的现象: 由于服 ...

  4. java web学习总结(十三) -------------------使用Session防止表单重复提交

    在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交. 一.表单重复提 ...

  5. [原创]java WEB学习笔记73:Struts2 学习之路-- strut2中防止表单重复提交

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  6. java web 学习十三(使用session防止表单重复提交)

    在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交. 一.表单重复提 ...

  7. [原创]java WEB学习笔记34:Session 案例 之 解决表单重复提交

    本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当 ...

  8. Java Web学习总结(12)——使用Session防止表单重复提交

    在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交. 一.表单重复提 ...

  9. 防止Web表单重复提交的方法总结

    在Web开发中,对于处理表单重复提交是经常要面对的事情.那么,存在哪些场景会导致表单重复提交呢?表单重复提交会带来什么问题?有哪些方法可以避免表单重复提交? 表单重复提交的场景 1.场景一:服务端未能 ...

随机推荐

  1. python 模块之-json

    python 模块json import json x="[null,true,false,1]" print(json.loads(x))   #---------------- ...

  2. HDU5384-Hotaru's problem-Manacher

    找出紧挨的三个回文串,例如abccbaabc ,形如ABA格式,其中AB为回文串.计算最长的长度. 首先用Manacher处理回文半径.然后就是找到两个点,都是偶数的回文串,并且共享了中间一段. 之后 ...

  3. Android学习第6天

    创建一个新的activity 四大组件需要在清单文件中配置 可在清单文件中配置多个启动图标过单个启动图标 Activity下的lable和icon属性可以和Application节点的属性不一样,默认 ...

  4. 【BZOJ4033】【HAOI2015】树上染色 树形DP

    题目描述 给你一棵\(n\)个点的树,你要把其中\(k\)个点染成黑色,剩下\(n-k\)个点染成白色.要求黑点两两之间的距离加上白点两两之间距离的和最大.问你最大的和是多少. \(n\leq 200 ...

  5. 使用gradle命令代替CUBA Studio,启动项目

    在cuba platform开发中,一开始都会使用CUBA Studio,这是一个脚手架,可以很方便的创建数据表.视图.Bean等.但是有时也会有奇怪的问题,比如不能读取本地maven 仓库,只读取远 ...

  6. 自学Python3.4-函数分类(匿名函数)

    自学Python之路-Python基础+模块+面向对象自学Python之路-Python网络编程自学Python之路-Python并发编程+数据库+前端自学Python之路-django 自学Pyth ...

  7. 【转】Ubuntu 64位系统安装交叉编译环境一直提醒 没有那个文件或目录

    安装交叉编译环境搞了一个晚上 一直提示 root@zqs-pc:~# arm-linux-gcc/usr/local/arm/4.3.2/bin/arm-linux-gcc: 行 3: /usr/lo ...

  8. X-PACK详解

    启用和禁用启用和禁用X-Pack功能默认情况下,所有X-Pack功能都被启用.您可以启用或禁用特定的X-Pack功能elasticsearch.yml,kibana.yml以及logstash.yml ...

  9. Nginx log日志切割shell

    #!/bin/bash#此脚本用于自动分割Nginx的日志,包括access.log和error.log#每天00:00执行此脚本 将前一天的access.log重命名为access-xxxx-xx- ...

  10. Eclipse Memory Analyzer(MAT)使用

    https://user.qzone.qq.com/731573705/blog/1436389384 Eclipse Memory Analyzer(MAT)使用  一.OutOfMemoryErr ...