一、表單重複送出
表單重複送出第一種情況:
送出完表單,伺服器使用請求轉來進行頁面跳轉。這個時候,使用者按下功能鍵 F5,就會發起最後一次的請求,造成表單重複送出問題。這種情況可以使用重定向來進行跳轉。
// 如果是請求轉發的話,浏覽器會儲存最後一次請求,以及所有參數,重新整理會繼續送出表單項,
//使用重定向則是新的一次請求,重定向到list,相當于最後一次請求是list,是以即使重新整理,還是在list頁面
response.sendRedirect(request.getContextPath() + "/");
表單重複送出第二種情況:
使用者正常送出伺服器,但是由于網絡延遲等原因,遲遲未收到伺服器的響應,這個時候如果多點了幾次送出操作,也會造成表單重複送出。
表單重複送出第三種情況:
使用者正常送出伺服器。伺服器也沒有延遲,但是送出完成後,使用者回退浏覽器,然後重新送出,這樣也會造成表單重複送出。
二、驗證碼解決表單重複送出的底層原理

使用谷歌 kaptcha 圖檔驗證碼
在
web.xml
中去配置用于生成驗證碼的
Servlet
程式
<servlet>
<servlet-name>KaptchaServlet</servlet-name>
<servlet-class>com.google.code.kaptcha.servlet.KaptchaServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>KaptchaServlet</servlet-name>
<url-pattern>/kaptcha.jpg</url-pattern>
</servlet-mapping>
在伺服器擷取谷歌生成的驗證碼和用戶端發送過來的驗證碼比較使用
protected void regist(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//擷取Session中的驗證碼
String token = (String) request.getSession().getAttribute(KAPTCHA_SESSION_KEY);
//删除Session中的驗證碼
request.getSession().removeAttribute(KAPTCHA_SESSION_KEY);
//1.擷取請求的參數
String username = request.getParameter("username");
String password = request.getParameter("password");
String email = request.getParameter("email");
String code = request.getParameter("code");
User user = WebUtils.copyParamToBean(request.getParameterMap(), new User());
//2.檢查驗證碼是否正确
if (token != null && token.equalsIgnoreCase(code)){
//3.驗證碼正确,檢查使用者名是否可用
if (userService.existUsername(username)){
System.out.println("使用者名[" + username + "]已存在!");
//把回顯資訊儲存到request域中
request.setAttribute("msg","使用者名已存在!");
request.setAttribute("username",username);
request.setAttribute("email",email);
request.getRequestDispatcher("/pages/user/regist.jsp").forward(request,response);
}else {
userService.registerUser(user);
request.getRequestDispatcher("/pages/user/regist_success.jsp").forward(request,response);
}
}else {
//把回顯資訊儲存到request域中
request.setAttribute("msg","驗證碼錯誤!");
request.setAttribute("username",username);
request.setAttribute("email",email);
//4.驗證碼不正确,跳回注冊頁面
request.getRequestDispatcher("/pages/user/regist.jsp").forward(request,response);
}
}
還可以實作切換驗證碼
//給驗證碼綁定切換圖檔的單擊事件
$("#code_img").click(function () {
//在事件響應的function函數中有一個this對象,這個this對象就是目前正在響應事件的dom對象
//這裡的this就是驗證碼圖檔響應事件,是以this就表示<img/>這個标簽
//src屬性表示驗證碼img标簽的圖檔路徑,src可讀可寫,指派之後會重新發起一次請求
//末尾加上時間戳是為了使得每次重新整理驗證碼請求位址不一樣,進而跳過浏覽器緩存
this.src = "${basePath}/kaptcha.jpg";
});