爲何會發生表單重複提交呢?javascript
在平時開發中,若是網速比較慢的狀況下,用戶提交表單後,發現服務器半天都沒有響應,那麼用戶可能會覺得是本身沒有提交表單,就會再點擊提交按鈕重複提交表單,咱們在開發中必須防止表單重複提交。html
表單提交後用戶點擊【刷新】按鈕致使表單重複提交前端
用戶提交表單後,點擊瀏覽器的【後退】按鈕回退到表單頁面後進行再次提交java
<script type="text/javascript"> var isFlag = false; //表單是否已經提交標識,默認爲false function 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(令牌)。session
<%@ 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 { @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; } }
簡單來講:經過session吧sessionTonken傳到前端,而後前端input使用隱藏域來保存sessionToken,name是tonken,在後臺獲取到sessionTonken和tonken的值,對比一下,第一次的時候確定會true,而後就刪除sessionTonken的值,第二次在對比一下,確定是false了