精华内容
下载资源
问答
  • 表单重复提交解决方案

    千次阅读 2020-04-07 10:37:38
    表单重复提交是在多用户Web应用中最常见、带来很多麻烦的一个问题。有很多的应用场景都会遇到重复提交问题,比如:1. 点击提交按钮两次。2. 点击刷新按钮。3. 使用浏览器后退按钮重复之前的操作,导致重复提交表单。...

     表单重复提交是在多用户Web应用中最常见、带来很多麻烦的一个问题。有很多的应用场景都会遇到重复提交问题,比如:1. 点击提交按钮两次。2. 点击刷新按钮。3. 使用浏览器后退按钮重复之前的操作,导致重复提交表单。4. 使用浏览器历史记录重复提交表单。5. 浏览器重复的HTTP请求。

      用户提交表单时可能因为网速的原因,或者网页被恶意刷新,致使同一条记录重复插入到数据库中,这是一个比较棘手的问题。我们可以从客户端和服务器端一起着手,设法避免同一表单的重复提交。

     

    一. 服务端解决方法

    1. 在session中存放一个特殊标志。

       在服务器端,生成一个唯一的标识符,将它存入session,同时将它写入表单的隐藏字段中,然后将表单页面发给浏览器,用户录入信息后点击提交,在服务器端,获取表单中隐藏字段的值,与session中的唯一标识符比较,相等说明是首次提交,就处理本次请求,然后将session中的唯一标识符移除;不相等说明是重复提交,就不再处理。这使你的web应用有了更高级的XSRF保护。

    2. 使用header函数转向。

       那就是当用户提交表单,服务器端处理后立即转向其他的页面。
    这样,即使用户使用刷新键,也不会导致表单的重复提交,因为已经转向新的页面,而这个页面脚本已经不理会任何提交的数据了。

    3. 借助数据库。

             insert使用唯一索引, update使用 乐观锁/悲观锁 version版本法

     

    二. 客户端解决方法

    1. js禁掉提交按钮。

       表单提交后使用Javascript使提交按钮disable。这种方法防止心急的用户多次点击按钮。但有个问题,如果客户端把Javascript给禁止掉,这种方法就无效了。

    2. 使用Post/Redirect/Get模式。

       在提交后执行页面重定向,这就是所谓的Post-Redirect-Get (PRG)模式。简言之,当用户提交了表单后,你去执行一个客户端的重定向,转到提交成功信息页面。
    这能避免用户按F5导致的重复提交,而其也不会出现浏览器表单重复提交的警告,也能消除按浏览器前进和后退按导致的同样问题。

     

    三、实例代码

    以Bootstrap插件为例:

    1.在按钮中加入data-loading-text,即点击按钮后显示的文字

    <button type="submit" class="btn btn-primary btn-check" data-loading-text="保存中...">保存</button>

    2.当点击按钮后禁用按钮,并显示data-loading-text文字

    $(".btn-check").click(function () { 
        $(this).button('loading');//禁用按钮并显示提交中 
        // $(this).button('reset');//重置按钮 
    }); 

    3.效果

     

    展开全文
  • 表单重复提交解决方案(防止Http重复提交 场景模拟 创建一个from.jsp页面 &amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot; pageEncoding=&...

    表单重复提交解决方案(防止Http重复提交

    场景模拟
    创建一个from.jsp页面

    <%@ page language="java" contentType="text/html; charset=UTF-8"
    	pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
      <head>
        <title>Form表单</title>
      </head>
      
      <body>
          <form action="${pageContext.request.contextPath}/DoFormServlet" method="post">
            用户名:<input type="text" name="userName">
            <input type="submit" value="提交" id="submit">
        </form>
      </body>
    </html>
    

    DoFormServlet 代码

    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    @WebServlet("/DoFormServlet")
    public class DoFormServlet extends HttpServlet {
    
    	@Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    	req.setCharacterEncoding("UTF-8");
    	String userName = req.getParameter("userName");
    	try {
    		Thread.sleep(300);
    	} catch (Exception e) {
    		// TODO: handle exception
    	}
    	System.out.println("往数据库插入数据...."+userName);
    	resp.getWriter().write("success");
    }
    }
    

    网络延时
    在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交。
    重新刷新
    表单提交后用户点击【刷新】按钮导致表单重复提交
    点击浏览器的【后退】按钮回退到表单页面后进行再次提交
    用户提交表单后,点击浏览器的【后退】按钮回退到表单页面后进行再次提交

    解决方案 使用javascript 解决

    既然存在上述所说的表单重复提交问题,那么我们就要想办法解决,比较常用的方法是采用JavaScript来防止表单重复提交,具体做法如下:
    修改form.jsp页面,添加如下的JavaScript代码来防止表单重复提交
    代码:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
    	pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <title>Form表单</title>
    <script type="text/javascript">
    	var isFlag = false; //表单是否已经提交标识,默认为false
    
    	function submitFlag() {
    
    		if (!isFlag) {
    			isFlag = true;
    			return true;
    		} else {
    			return false;
    		}
    
    	}
    </script>
    </head>
    
    <body>
    	<form action="${pageContext.request.contextPath}/DoFormServlet"
    		method="post" onsubmit="return submitFlag()">
    		用户名:<input type="text" name="userName"> <input type="submit"
    			value="提交" id="submit">
    	</form>
    </body>
    </html>
    

    除了用这种方式之外,经常见的另一种方式就是表单提交之后,将提交按钮设置为不可用,让用户没有机会点击第二次提交按钮,代码如下:

     function dosubmit(){
        //获取表单提交按钮
        var btnSubmit = document.getElementById("submit");
        //将表单提交按钮设置为不可用,这样就可以避免用户再次点击提交按钮
        btnSubmit.disabled= "disabled";
        //返回true让表单可以正常提交
        return true;
    }
    

    使用后端提交解决

    对于【场景二】和【场景三】导致表单重复提交的问题,既然客户端无法解决,那么就在服务器端解决,在服务器端解决就需要用到session了。
    具体的做法:在服务器端生成一个唯一的随机标识号,专业术语称为Token(令牌),同时在当前用户的Session域中保存这个Token。然后将Token发送到客户端的Form表单中,在Form表单中使用隐藏域来存储这个Token,表单提交的时候连同这个Token一起提交到服务器端,然后在服务器端判断客户端提交上来的Token与服务器端生成的Token是否一致,如果不一致,那就是重复提交了,此时服务器端就可以不处理重复提交的表单。如果相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。

    在下列情况下,服务器程序将拒绝处理用户提交的表单请求:
    1.存储Session域中的Token(令牌)与表单提交的Token(令牌)不同。
    2.当前用户的Session中不存在Token(令牌)。
    3.用户提交的表单数据中没有Token(令牌)。

    转发代码:

     @WebServlet("/ForwardServlet")
        public class ForwardServlet extends HttpServlet {
        	@Override
        	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        		req.getSession().setAttribute("sesionToken", TokenUtils.getToken());
        		req.getRequestDispatcher("form.jsp").forward(req, resp);
        	}
        }
    

    转发页面:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
    	pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <title>Form表单</title>
    
    </head>
    
    <body>
    	<form action="${pageContext.request.contextPath}/DoFormServlet"
    		method="post" onsubmit="return dosubmit()">
    		<input type="hidden" name="token" value="${sesionToken}"> 用户名:<input type="text"
    			name="userName"> <input type="submit" value="提交" id="submit">
    	</form>
    </body>
    </html>
    

    后端Java代码:

    @WebServlet("/DoFormServlet")
    public class DoFormServlet extends HttpServlet {
    	@Override
    	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		req.setCharacterEncoding("UTF-8");
    		boolean flag = isFlag(req);
    		if (!flag) {
    			resp.getWriter().write("已经提交...");
    			System.out.println("数据已经提交了..");
    			return;
    		}
    		String userName = req.getParameter("userName");
    		try {
    			Thread.sleep(300);
    		} catch (Exception e) {
    			// TODO: handle exception
    		}
    		System.out.println("往数据库插入数据...." + userName);
    		resp.getWriter().write("success");
    	}
    
    	public boolean isFlag(HttpServletRequest request) {
    		HttpSession session = request.getSession();
    		String sesionToken = (String) session.getAttribute("sesionToken");
    		String token = request.getParameter("token");
    		if (!(token.equals(sesionToken))) {
    			return false;
    		}
    		session.removeAttribute("sesionToken");
    		return true;
    	}
    }
    
     
    
    展开全文
  • 表单重复提交是在多用户Web应用中最常见、带来很多麻烦的一个问题。有很多的应用场景都会遇到重复提交问题,比如: 点击提交按钮两次。 点击刷新按钮。 使用浏览器后退按钮重复之前的操作,导致重复提交表单。 使用...
    • 概述

    表单重复提交是在多用户Web应用中最常见、带来很多麻烦的一个问题。有很多的应用场景都会遇到重复提交问题,比如:

    点击提交按钮两次。
    点击刷新按钮。
    使用浏览器后退按钮重复之前的操作,导致重复提交表单。
    使用浏览器历史记录重复提交表单。
    浏览器重复的HTTP请求。

    用户提交表单时可能因为网速的原因,或者网页被恶意刷新,致使同一条记录重复插入到数据库中,这是一个比较棘手的问题。我们可以从客户端和服务器端一起着手,设法避免同一表单的重复提交

    • 1、使用javascript 解决

    既然存在上述所说的表单重复提交问题,那么我们就要想办法解决,比较常用的方法是采用JavaScript来防止表单重复提交,

    具体做法如下:

    修改form.jsp页面,添加如下的JavaScript代码来防止表单重复提交

    <%@ page language="java" contentType="text/html; charset=UTF-8"
    	pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <title>Form表单</title>
    <script type="text/javascript">
    	var isFlag = false; //表单是否已经提交标识,默认为false
    
    	function submitFlag() {
    
    		if (isFlag == false) {
    			isFlag = true;
    			return true;
    		} else {
    			return false;
    		}
    
    	}
    </script>
    </head>
    
    <body>
    	<form action="${pageContext.request.contextPath}/DoFormServlet"
    		method="post" onsubmit="return submitFlag()">
    		用户名:<input type="text" name="userName"> <input type="submit"
    			value="提交" id="submit">
    	</form>
    </body>
    </html>

    除了用这种方式之外,经常见的另一种方式就是表单提交之后,将提交按钮设置为不可用,让用户没有机会点击第二次提交按钮,代码如下:

    function dosubmit(){
        //获取表单提交按钮
        var btnSubmit = document.getElementById("submit");
        //将表单提交按钮设置为不可用,这样就可以避免用户再次点击提交按钮
        btnSubmit.disabled= "disabled";
        //返回true让表单可以正常提交
        return true;
    }
    • 2、使用后端提交解决

    若客户端无法解决,那么就在服务器端解决,在服务器端解决就需要用到session了;

    具体的做法:在服务器端生成一个唯一的随机标识号,专业术语称为Token(令牌),同时在当前用户的Session域中保存这个Token。然后将Token发送到客户端的Form表单中,在Form表单中使用隐藏域来存储这个Token,表单提交的时候连同这个Token一起提交到服务器端,然后在服务器端判断客户端提交上来的Token与服务器端生成的Token是否一致,如果不一致,那就是重复提交了,此时服务器端就可以不处理重复提交的表单。如果相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。
    在下列情况下,服务器程序将拒绝处理用户提交的表单请求:

    存储Session域中的Token(令牌)与表单提交的Token(令牌)不同。

    当前用户的Session中不存在Token(令牌)。

    用户提交的表单数据中没有Token(令牌)。

    转发代码:

    @WebServlet("/ForwardServlet")
    public class ForwardServlet extends HttpServlet {
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		req.getSession().setAttribute("sesionToken", TokenUtils.getToken());
    		req.getRequestDispatcher("form.jsp").forward(req, resp);
    	}
    }

    转发页面:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
    	pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <title>Form表单</title>
    
    </head>
    
    <body>
    	<form action="${pageContext.request.contextPath}/DoFormServlet"
    		method="post" onsubmit="return dosubmit()">
    		<input type="hidden" name="token" value="${sesionToken}"> 用户名:<input type="text"
    			name="userName"> <input type="submit" value="提交" id="submit">
    	</form>
    </body>
    </html>

    后端Java代码:

    @WebServlet("/DoFormServlet")
    public class DoFormServlet extends HttpServlet {
    	@Override
    	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		req.setCharacterEncoding("UTF-8");
    		boolean flag = isFlag(req);
    		if (!flag) {
    			resp.getWriter().write("已经提交...");
    			System.out.println("数据已经提交了..");
    			return;
    		}
    		String userName = req.getParameter("userName");
    		try {
    			Thread.sleep(300);
    		} catch (Exception e) {
    			// TODO: handle exception
    		}
    		System.out.println("往数据库插入数据...." + userName);
    		resp.getWriter().write("success");
    	}
    
    	public boolean isFlag(HttpServletRequest request) {
    		HttpSession session = request.getSession();
    		String sesionToken = (String) session.getAttribute("sesionToken");
    		String token = request.getParameter("token");
    		if (!(token.equals(sesionToken))) {
    			return false;
    		}
    		session.removeAttribute("sesionToken");
    		return true;
    	}
    }
    

     

    展开全文
  • java web 防止表单重复提交解决方案

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

    转至:http://www.cnblogs.com/xdp-gacl/p/3859416.html

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

    一、表单重复提交的常见应用场景

    有如下的form.jsp页面

    复制代码
     1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
     2 <!DOCTYPE HTML>
     3 <html>
     4   <head>
     5     <title>Form表单</title>
     6   </head>
     7   
     8   <body>
     9       <form action="${pageContext.request.contextPath}/servlet/DoFormServlet" method="post">
    10         用户名:<input type="text" name="username">
    11         <input type="submit" value="提交" id="submit">
    12     </form>
    13   </body>
    14 </html>
    复制代码

      form表单提交到DoFormServlet进行处理

    复制代码
     1 package xdp.gacl.session;
     2 
     3 import java.io.IOException;
     4 import javax.servlet.ServletException;
     5 import javax.servlet.http.HttpServlet;
     6 import javax.servlet.http.HttpServletRequest;
     7 import javax.servlet.http.HttpServletResponse;
     8 
     9 public class DoFormServlet extends HttpServlet {
    10 
    11     public void doGet(HttpServletRequest request, HttpServletResponse response)
    12             throws ServletException, IOException {
    13         //客户端是以UTF-8编码传输数据到服务器端的,所以需要设置服务器端以UTF-8的编码进行接收,否则对于中文数据就会产生乱码
    14         request.setCharacterEncoding("UTF-8");
    15         String userName = request.getParameter("username");
    16         try {
    17             //让当前的线程睡眠3秒钟,模拟网络延迟而导致表单重复提交的现象
    18             Thread.sleep(3*1000);
    19         } catch (InterruptedException e) {
    20             e.printStackTrace();
    21         }
    22         System.out.println("向数据库中插入数据:"+userName);
    23     }
    24 
    25     public void doPost(HttpServletRequest request, HttpServletResponse response)
    26             throws ServletException, IOException {
    27         doGet(request, response);
    28     }
    29 
    30 }
    复制代码

      如果没有进行form表单重复提交处理,那么在网络延迟的情况下下面的操作将会导致form表单重复提交多次

    1.1、场景一:在网络延迟的情况下让用户有时间点击多次submit按钮导致表单重复提交

      演示动画如下所示:

     1.2、场景二:表单提交后用户点击【刷新】按钮导致表单重复提交

    演示动画如下所示:

      点击浏览器的刷新按钮,就是把浏览器上次做的事情再做一次,因为这样也会导致表单重复提交。

    1.3、场景三:用户提交表单后,点击浏览器的【后退】按钮回退到表单页面后进行再次提交

    演示动画如下所示:

    二、利用JavaScript防止表单重复提交

      既然存在上述所说的表单重复提交问题,那么我们就要想办法解决,比较常用的方法是采用JavaScript来防止表单重复提交,具体做法如下:

    修改form.jsp页面,添加如下的JavaScript代码来防止表单重复提交

    复制代码
     1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
     2 <!DOCTYPE HTML>
     3 <html>
     4   <head>
     5     <title>Form表单</title>
     6         <script type="text/javascript">
     7         var isCommitted = false;//表单是否已经提交标识,默认为false
     8         function dosubmit(){
     9             if(isCommitted==false){
    10                 isCommitted = true;//提交表单后,将表单是否已经提交标识设置为true
    11                 return true;//返回true让表单正常提交
    12             }else{
    13                 return false;//返回false那么表单将不提交
    14             }
    15         }
    16     </script>
    17   </head>
    18   
    19   <body>
    20       <form action="${pageContext.request.contextPath}/servlet/DoFormServlet" onsubmit="return dosubmit()" method="post">
    21         用户名:<input type="text" name="username">
    22         <input type="submit" value="提交" id="submit">
    23     </form>
    24   </body>
    25 </html>
    复制代码

      我们看看使用了JavaScript来防止表单提交重复是否可以成功,运行效果如下:

      可以看到,针对"在网络延迟的情况下让用户有时间点击多次submit按钮导致表单重复提交"这个应用场景,使用JavaScript是可以解决这个问题的,解决的做法就是"用JavaScript控制Form表单只能提交一次"。

      除了用这种方式之外,经常见的另一种方式就是表单提交之后,将提交按钮设置为不可用,让用户没有机会点击第二次提交按钮,代码如下:

    复制代码
    1 function dosubmit(){
    2     //获取表单提交按钮
    3     var btnSubmit = document.getElementById("submit");
    4     //将表单提交按钮设置为不可用,这样就可以避免用户再次点击提交按钮
    5     btnSubmit.disabled= "disabled";
    6     //返回true让表单可以正常提交
    7     return true;
    8 }
    复制代码

    运行效果如下:

       另外还有一种做法就是提交表单后,将提交按钮隐藏起来,这种做法和将提交按钮设置为不可用是差不多的,个人觉得将提交按钮隐藏影响到页面布局的美观,并且可能会让用户误以为是bug(怎么我一点击按钮,按钮就不见了呢?用户可能会有这样的疑问),我个人在开发中用得比较多的是表单提交后,将提交按钮设置为不可用,反正使用JavaScript防止表单重复提交的做法都是差不多的,目的都是让表单只能提交一次,这样就可以做到表单不重复提交了。

      使用JavaScript防止表单重复提交的做法只对上述提交到导致表单重复提交的三种场景中的【场景一】有效,而对于【场景二】和【场景三】是没有用,依然无法解决表单重复提交问题。

    三、利用Session防止表单重复提交

      对于【场景二】和【场景三】导致表单重复提交的问题,既然客户端无法解决,那么就在服务器端解决,在服务器端解决就需要用到session了。

      具体的做法:在服务器端生成一个唯一的随机标识号,专业术语称为Token(令牌),同时在当前用户的Session域中保存这个Token。然后将Token发送到客户端的Form表单中,在Form表单中使用隐藏域来存储这个Token,表单提交的时候连同这个Token一起提交到服务器端,然后在服务器端判断客户端提交上来的Token与服务器端生成的Token是否一致,如果不一致,那就是重复提交了,此时服务器端就可以不处理重复提交的表单。如果相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。
      在下列情况下,服务器程序将拒绝处理用户提交的表单请求:

    1. 存储Session域中的Token(令牌)与表单提交的Token(令牌)不同。
    2. 当前用户的Session中不存在Token(令牌)
    3. 用户提交的表单数据中没有Token(令牌)

    看具体的范例:

      1.创建FormServlet,用于生成Token(令牌)和跳转到form.jsp页面

    复制代码
     1 package xdp.gacl.session;
     2 
     3 import java.io.IOException;
     4 import javax.servlet.ServletException;
     5 import javax.servlet.http.HttpServlet;
     6 import javax.servlet.http.HttpServletRequest;
     7 import javax.servlet.http.HttpServletResponse;
     8 
     9 public class FormServlet extends HttpServlet {
    10     private static final long serialVersionUID = -884689940866074733L;
    11 
    12     public void doGet(HttpServletRequest request, HttpServletResponse response)
    13             throws ServletException, IOException {
    14 
    15         String token = TokenProccessor.getInstance().makeToken();//创建令牌
    16         System.out.println("在FormServlet中生成的token:"+token);
    17         request.getSession().setAttribute("token", token);  //在服务器使用session保存token(令牌)
    18         request.getRequestDispatcher("/form.jsp").forward(request, response);//跳转到form.jsp页面
    19     }
    20 
    21     public void doPost(HttpServletRequest request, HttpServletResponse response)
    22             throws ServletException, IOException {
    23         doGet(request, response);
    24     }
    25 
    26 }
    复制代码

      2.在form.jsp中使用隐藏域来存储Token(令牌)

    复制代码
     1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
     2 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
     3 <html>
     4 <head>
     5 <title>form表单</title>
     6 </head>
     7 
     8 <body>
     9     <form action="${pageContext.request.contextPath}/servlet/DoFormServlet" method="post">
    10         <%--使用隐藏域存储生成的token--%>
    11         <%--
    12             <input type="hidden" name="token" value="<%=session.getAttribute("token") %>">
    13         --%>
    14         <%--使用EL表达式取出存储在session中的token--%>
    15         <input type="hidden" name="token" value="${token}"/> 
    16         用户名:<input type="text" name="username"> 
    17         <input type="submit" value="提交">
    18     </form>
    19 </body>
    20 </html>
    复制代码

      3.DoFormServlet处理表单提交

    复制代码
     1 package xdp.gacl.session;
     2 
     3 import java.io.IOException;
     4 import javax.servlet.ServletException;
     5 import javax.servlet.http.HttpServlet;
     6 import javax.servlet.http.HttpServletRequest;
     7 import javax.servlet.http.HttpServletResponse;
     8 
     9 public class DoFormServlet extends HttpServlet {
    10 
    11     public void doGet(HttpServletRequest request, HttpServletResponse response)
    12                 throws ServletException, IOException {
    13 
    14             boolean b = isRepeatSubmit(request);//判断用户是否是重复提交
    15             if(b==true){
    16                 System.out.println("请不要重复提交");
    17                 return;
    18             }
    19             request.getSession().removeAttribute("token");//移除session中的token
    20             System.out.println("处理用户提交请求!!");
    21         }
    22         
    23         /**
    24          * 判断客户端提交上来的令牌和服务器端生成的令牌是否一致
    25          * @param request
    26          * @return 
    27          *         true 用户重复提交了表单 
    28          *         false 用户没有重复提交表单
    29          */
    30         private boolean isRepeatSubmit(HttpServletRequest request) {
    31             String client_token = request.getParameter("token");
    32             //1、如果用户提交的表单数据中没有token,则用户是重复提交了表单
    33             if(client_token==null){
    34                 return true;
    35             }
    36             //取出存储在Session中的token
    37             String server_token = (String) request.getSession().getAttribute("token");
    38             //2、如果当前用户的Session中不存在Token(令牌),则用户是重复提交了表单
    39             if(server_token==null){
    40                 return true;
    41             }
    42             //3、存储在Session中的Token(令牌)与表单提交的Token(令牌)不同,则用户是重复提交了表单
    43             if(!client_token.equals(server_token)){
    44                 return true;
    45             }
    46             
    47             return false;
    48         }
    49 
    50     public void doPost(HttpServletRequest request, HttpServletResponse response)
    51             throws ServletException, IOException {
    52         doGet(request, response);
    53     }
    54 
    55 }
    复制代码

      生成Token的工具类TokenProccessor

    复制代码
     1 package xdp.gacl.session;
     2 
     3 import java.security.MessageDigest;
     4 import java.security.NoSuchAlgorithmException;
     5 import java.util.Random;
     6 import sun.misc.BASE64Encoder;
     7 
     8 public class TokenProccessor {
     9 
    10     /*
    11      *单例设计模式(保证类的对象在内存中只有一个)
    12      *1、把类的构造函数私有
    13      *2、自己创建一个类的对象
    14      *3、对外提供一个公共的方法,返回类的对象
    15      */
    16     private TokenProccessor(){}
    17     
    18     private static final TokenProccessor instance = new TokenProccessor();
    19     
    20     /**
    21      * 返回类的对象
    22      * @return
    23      */
    24     public static TokenProccessor getInstance(){
    25         return instance;
    26     }
    27     
    28     /**
    29      * 生成Token
    30      * Token:Nv6RRuGEVvmGjB+jimI/gw==
    31      * @return
    32      */
    33     public String makeToken(){  //checkException
    34         //  7346734837483  834u938493493849384  43434384
    35         String token = (System.currentTimeMillis() + new Random().nextInt(999999999)) + "";
    36         //数据指纹   128位长   16个字节  md5
    37         try {
    38             MessageDigest md = MessageDigest.getInstance("md5");
    39             byte md5[] =  md.digest(token.getBytes());
    40             //base64编码--任意二进制编码明文字符   adfsdfsdfsf
    41             BASE64Encoder encoder = new BASE64Encoder();
    42             return encoder.encode(md5);
    43         } catch (NoSuchAlgorithmException e) {
    44             throw new RuntimeException(e);
    45         }
    46     }
    47 }
    复制代码

      首先访问FormServlet,在FormServlet中生成Token之后再重定向到form.jsp页面,这次是在服务器端处理表单重复提交的,运行效果如下:

      从运行效果中可以看到,通过这种方式处理表单重复提交,可以解决上述的场景二和场景三中出现的表单重复提交问题。

    展开全文
  • 引发表单重复提交的一些场景: 网络延时  在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在...
  • 防止表单重复提交解决方案

    千次阅读 2019-04-28 21:29:48
    所谓表单重复提交就是同一份信息多次发给服务端 场景 点击F5刷新页面: 当用户点击submit将已经写好的表单数据提交到服务器时,可以在浏览器的url看到地址和参数的变化,但因为网速等问题,用户当前页面并未刷新,...
  • 表单重复提交问题解决方案

    千次阅读 2018-09-18 17:10:25
    2.网速较慢的情况,我们让表单中的提交按钮只能提交一次,然后就不能再次点击了 &lt;form action="FormServlet" method="post"&gt; &lt;input type="text" name="...
  • 怎样防止表单重复提交,通过搜索引擎能搜到很多结果,但很零散,系统性不强,正好前几天做了这个功能,决定记录下来。 根据数据流向的过程,分别在三个“点”控制表单的重复提交,如下:第一,用户触发submit时,...
  • (虽然这个方案解决不了我的问题... 在平时的开发过程中,经常可以遇到表单重复提交的问题,如做一个注册页面,如果表单重复提交,那么一个用户就会注册多次,重复提交主要由于两种原因。   1、 一是,服务器处理
  • 方案一(使用session):jsp页面中controller中
  • 解决表单重复提交解决方案——在服务端对Token进行验证 1、在idea中建立一个springboot项目 2、在templates目录下建立一个index.html文件 <!DOCTYPE html> <... xmlns:contex...
  • javaweb防止表单重复提交的几种解决方案 在javaweb方向做开发的小伙伴们,肯定都会遇到表单重复提交的问题。 javaweb防止表单重复提交的几种解决方案 这种问题出现的原因或者说应用场景大致如下: 网络延迟,...
  • springboot解决form表单重复提交方案

    千次阅读 2019-05-17 11:15:57
     在实际业务系统应用过程中,都会存在一个表单数据重复提交的问题。针对这个问题网上也存在N多种解决方案。  为节省选择时间,因此在这N多种方案中,我整理了自认为从根本上解决重复提交的问题的一个最优方案。 ...
  •  在平时的开发过程中,经常可以遇到表单重复提交的问题,如做一个注册页面,如果表单重复提交,那么一个用户就会注册多次,重复提交主要由于两种原因。  1、 一是,服务器处理时间久。当用户在表单中填完信息,...
  • 重复提交解决方案

    2019-05-17 17:17:07
    重复提交解决方案 传统方式**(不推荐) ** 首先我们介绍下之前传统的防重复提交方式: **1:前端处理: ** 思路如下: function dosubmit(){ //第一步,我们需要获取表单的提交按钮。 var btnSubmit = ...
  • 表单重复提交

    2017-08-30 09:54:45
    【1】提交完表单以后,不做其他操作,直接刷新页面,表单会提交多次 原因是,Servlet处理完...【2】点击提交按钮多次,这种情况也会导致表单重复提交 解决方案:使提交按钮只能点击一次。这得通过js来完成(疑惑:大
  • 1、什么是重复提交及重复提高带来的什么问题 在开发中,有很多也没设计表单数据的提交,如登录、注册等等;但如果用户点击了『登录』或『注册』时,点击浏览器『刷新按钮』刷新页面,如果不做处理此时会对同一组数据...
  • 重定向到其他信息页面解决方案 3.重定向到该页面解决。return HttpResponseRedirect('%s'%next),next为上级页面隐藏域中保存的上级页面的url 转载于:...
  • 解决表单重复提交

    2018-07-19 16:00:50
    记得前几次面试的时候,3家公司问了表单重复提交的问题,我回答的都不是特别好,虽然知道是个什么流程,但是因为只知道理论,所以面试官问的细一点就懵了 这次就写了一个demo测试一下之前的想法是否准确. 1 表单重复...
  • 阅读目录前言form重复提交场景解决方案一:前端利用JavaScript防止表单重复提交二:利用Session防止表单重复提交参考 前言 如果网速比较慢的情况下,用户点击的提交发现半天没有反映,于是又重新点击了几次提交按钮...
  • IP协议主要解决网络路由和寻址问题,TCP协议主要解决如何在IP层之上可靠的传递数据包,使在网络上的另一端收到发端发出的所有包,并且顺序与发出顺序一致。TCP有可靠,面向连接的特点。 如何理解HTT...
  • 参考网上的一些资料:通过前端 + 后端 一起来阻止表单重复提交 这边整理出2种 ,前端大家参考一下,我主要是用后端,跑一个demo实际的演示一下 源码我放到github上,欢迎大家下载:...
  • token机制详解 注:文内关于使用验证码图片的代码请参考我的另一篇博客 java Web项目中导入验证码图片功能步骤详解 ...解决方案:将转发改为重定向即可 2)由于网速或服务器的性能,导致处理请求满,用户重复点...
  • 解决表单重复提交问题

    千次阅读 多人点赞 2017-08-12 11:41:41
    表单重复提交类型:1. 提交完表单以后,不做其他操作,直接刷新页面,表单会提交多次。 产生原因: 1. 这种情况产生的根本原因是,Servlet处理完请求以后,直接转发到目标页面。 2. 这样整一个业务,只发送...
  • 接口重复提交解决方案

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 25,427
精华内容 10,170
关键字:

表单重复提交解决方案