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了