2019独角兽企业重金招聘Python工程师标准>>>
为什么会发生表单重复提交呢?
网络延时
在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交。
重新刷新
表单提交后用户点击【刷新】按钮导致表单重复提交
点击浏览器的【后退】按钮回退到表单页面后进行再次提交
用户提交表单后,点击浏览器的【后退】按钮回退到表单页面后进行再次提交
解决方案
使用javascript 解决
<script type="text/javascript">var isFlag = false; //表单是否已经提交标识,默认为falsefunction submitFlag() {if (!isFlag) {isFlag = true;return true;} else {return false;}}
</script>
2
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(令牌)。
<%@ 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>
@WebServlet("/DoFormServlet")
public class DoFormServlet extends HttpServlet {@Overrideprotected 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;}
}
简单来说:通过session吧sessionTonken传到前端,然后前端input使用隐藏域来保存sessionToken,name是tonken,在后台获取到sessionTonken和tonken的值,对比一下,第一次的时候肯定会true,然后就删除sessionTonken的值,第二次在对比一下,肯定是false了