什么情况下会出现表单重复提交?
1、网络延迟
2、重新刷新
3、点击浏览器的后退按钮回退到表单页面后进行再次提交
解决方案?
1、前端解决方案:让页面按钮只能点击一次或者将按钮设为点一次后就不可用(都不可靠,如果刷新还是会有重复提交)
修改form.jsp页面,添加如下的JavaScript代码来防止表单重复提交
代码:
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
除了用这种方式之外,经常见的另一种方式就是表单提交之后,将提交按钮设置为不可用,让用户没有机会点击第二次提交按钮,代码如下:
function dosubmit(){
//获取表单提交按钮
var btnSubmit = document.getElementById("submit");
//将表单提交按钮设置为不可用,这样就可以避免用户再次点击提交按钮
btnSubmit.disabled= "disabled";
//返回true让表单可以正常提交
return true;
}
2、后端解决方案:使用Token(令牌)+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(HttpServletRequestreq, HttpServletResponseresp)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"%>
后端java代码
@WebServlet("/DoFormServlet")
public class DoFormServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequestreq, HttpServletResponseresp)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 (Exceptione) {
// TODO: handle exception
}
System.out.println("往数据库插入数据...." +userName);
resp.getWriter().write("success");
}
public boolean isFlag(HttpServletRequestrequest) {
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;
}
}