表单的重复提交
1)重复提交的情况
1>在表单提交到一个Servlet,而Servlet又通过请求转发的方式响应了一个JSP(HTML)页面,此时地址栏还保留着Servlet的那个路径,在响应页面点击“刷新”。
2>在响应页面没有到达时重复点击“提交按钮”
3>点击“返回”,再点击“提交”
2)不是重复提交的情况
1>点击“返回”,“刷新”原表单页面,再“提交”
3)如何避免表单的重复提交
1>在表单中做一个标记,提交到Servlet时,检查标记是否存在且是否和预定义的标记一致,若一致,则受理请求,并销毁标记,若不一致或没有标记,则直接响应提示信息:“重复提交”
(1)仅提供一个隐藏域:<input type="hidden" name="token" value="YHS"/>行不通:没有办法清除固定的请求参数。
(2)把标记放在request中,行不通,因为表单页面刷新后,request已经被销毁,再提交表单是一个新的request。
(3)把标记放在session中,可以!
>在原表单页面,生成一个随机值token
>在原表单页面,把token值放入session属性中
>在原表单页面,把token值放入隐藏域中。
——提交表单
>在目标的servlet中:获取session和隐藏域中的token值
>比较两个值是否一致:若一致,受理请求,且把session域中的token属性清除
>若不一致,则直接响应提示页面:"重复提交"
原理:在原表单页面,创建一个session属性,和隐藏域,两个值开始时是一个相同的随机值,当进入servlet中比较两个值是否相同,相同删除session属性。
login.jsp
单击提交表单
点击返回,点击提交表单。
刷新原表单页面,连续点击提交
源码:
login.jsp
<%@ page import="java.util.Date" %><%-- Created by IntelliJ IDEA. User: dell Date: 2019/7/11 Time: 16:05 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>Title</title> </head> <body> <% String tokenValue = new Date().getTime() + ""; session.setAttribute("token",tokenValue); %> <form action="<%= request.getContextPath()%>/TokenServlet" method="post"> <input type="hidden" name="token" value="<%= tokenValue%>"> name: <input type="text" name="name"> <input type="submit" value="Submit"> </form> </body> </html>
tokenservlet
package com.demo.servlet; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import java.io.IOException; public class TokenServlet extends HttpServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } HttpSession session = req.getSession(); Object token = session.getAttribute("token"); String tokenValue = req.getParameter("token"); System.out.println(token); System.out.println(tokenValue); if (token!=null&&token.equals(tokenValue)){ session.removeAttribute("token"); }else{ resp.sendRedirect(req.getContextPath()+"/stoken/error.jsp"); return; } String name = req.getParameter("name"); System.out.println("name: " +name); resp.sendRedirect(req.getContextPath()+"/stoken/success.jsp"); } }