session的典型案例二:避免表单的重复提交

本文介绍了一种通过在表单中使用随机标记(token)来防止Web应用程序中表单重复提交的有效方法,包括实现流程及示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

重复提交的情况:

  1).在表单提交到servlet,而servlet又通过请求转发的方式响应了一个JSP页面,此时地址栏还保留着servlet的路径,在响应页面点击“刷新”。

  2).在有网络延时,相应页面没有到达时,重复点击“提交”按钮。

  3).返回第一个页面,点击提交。

不是重复提交的情况:

  1).页面回退到第一个页面,刷新页面,再次提交。

避免表单的重复提交

  调用RequestDispatcher.forword()方法,浏览器所保留的URL是先前的表单提交的URL,此时点击“刷新”,浏览器将再次提交用户先前输入的数据,引起重复提交

  如果采用sendRedirect()方法将客户端重定向到成功页面,将不会出现重复的问题。


如何避免表单的重复提交:在表单中做一个标记,提交到servlet时,检查标记是否存在且是否和预定义的标记一致,若一致,则受理请求,并销毁标记,若不一致或没有标记,则直接响应提示信息:“重复提交”。

1).仅提供一个隐藏域:

<input type="hidden" value="token" name="token">
    行不通:没有方法清除固定的请求参数。

2).把标记放入request中:行不通,因为表单页面刷新后,request已经被销毁,再提交表单是一个新的request。

3).把标记放入session中,可以。

>在原表单页面,生成一个随机值token

>在原表单页面,把token放入session和隐藏域中

>提交表单,在目标的servlet中获取session和隐藏域中的token值,比较两个值是否一致,若一致则success,且删除session中的token,若不一致则failed。

token.jsp:

<%--
  Created by IntelliJ IDEA.
  User: 123
  Date: 2017/9/30
  Time: 9:14
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java"
    import="java.util.*"
%>
<%
    String path = request.getContextPath();
    String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<html>
<head>
    <title>token page</title>
</head>
<body>
    <%
       String tokenVal=new Date().getTime()+"";
    %>
   <form action="<%=basePath%>token" method="post">
      <input type="hidden" value="<%= tokenVal %>" name="token">
       <% session.setAttribute("token",tokenVal); %>
       姓名:<input type="text" name="username">
       <input type="submit" value="提交">
   </form>
</body>
</html>


tokenservlet:

package com.sa.servlet;

import java.io.IOException;
import javax.servlet.http.*;
import javax.servlet.ServletException;

public class TokenServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        HttpSession session=request.getSession();
        Object obj=session.getAttribute("token");
        String tokenVal=request.getParameter("token");
        if(obj!=null && obj.toString().equals(tokenVal)){
            session.removeAttribute("token");
        }else{
            String path = request.getContextPath();
            response.sendRedirect(path+"/pages/failed.jsp");
            return;
        }
        String username=request.getParameter("username");
        System.out.println("username:"+username);

        request.getRequestDispatcher("/pages/success.jsp").forward(request,response);

    }


}


success.jsp:

<%--
  Created by IntelliJ IDEA.
  User: 123
  Date: 2017/9/30
  Time: 10:14
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>SUCCESS</title>
</head>
<body>
   <h2>成功</h2>
</body>
</html>
failed:

<%--
  Created by IntelliJ IDEA.
  User: 123
  Date: 2017/9/30
  Time: 11:32
  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>
   <h1>请勿重复提交</h1>
</body>
</html>

测试:

第一次提交:

返回再次点击提交:







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值