表單重複提交問題

爲何會發生表單重複提交呢?javascript

網絡延時

 在平時開發中,若是網速比較慢的狀況下,用戶提交表單後,發現服務器半天都沒有響應,那麼用戶可能會覺得是本身沒有提交表單,就會再點擊提交按鈕重複提交表單,咱們在開發中必須防止表單重複提交。html

從新刷新

表單提交後用戶點擊【刷新】按鈕致使表單重複提交前端

點擊瀏覽器的【後退】按鈕回退到表單頁面後進行再次提交

用戶提交表單後,點擊瀏覽器的【後退】按鈕回退到表單頁面後進行再次提交java

 

解決方案

使用javascript 解決

<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了

相關文章
相關標籤/搜索