一、会造成表单重新提交的情况:
- 在用户使用我们应用的时候经常会出现在网络延迟的情况下让用户有时间点击多次提交按钮;
- 表单提交后用户点击【刷新】按钮;
- 用户提交表单后,点击浏览器的【后退】按钮回退到表单页面后再次点击提交按钮。
以上这些情况都会导致重复提交表单,我们在开发中必须防止这种情况的出现。
二、我们怎样避免用户对表单进行重复提交?下面我们一起通过简单的代码例子进行讲解,首先我们创建一个提交页面from.jsp,代码如下:
<% session.setAttribute("token", System.nanoTime()+""); %> <form action="formServlet" method="post"> <input type="hidden" name="token" value="<%=session.getAttribute("token")%>"> 用户名:<input type="text" name="username"> <input type="submit" value="提交"> </form> |
在上述代码中,我们生产了一个随机数作为token(专业术语叫做令牌),之后我们把这个令牌放入到session当中,在表单中我们把它令牌放到隐藏域与用户名一起进行提交到一个servlet当中,servlet代码如下:
response.setContentType("text/html;charset=UTF-8"); PrintWriter out=response.getWriter(); //获取表单提交的token String requestToken = request.getParameter("token"); //取出存储在Session中的token String sessionToken = (String) request.getSession().getAttribute("token"); //表单数据中没有token,表单重复提交 if(requestToken==null){ out.println("表单重复提交"); }else if(sessionToken==null){//Session中不存在Token,表单重复提交 out.println("表单重复提交"); }else if(!requestToken.equals(sessionToken)){//Session中的Token与表单提交的Token不同,表单重复提交 out.println("表单重复提交"); }else{ request.getSession().removeAttribute("token");//移除session中的token String userName = request.getParameter("username"); try { //让当前的线程睡眠5秒钟,模拟业务处理时间或网络延迟 Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); }
} |
在上述代码中我们获取到提交的令牌值和session当中保存的令牌值,如果这个两个值都不为空且相等的话,我们就认为表单是第一次提交,然后吧session中的令牌移除,开始做业务处理,否则的话就表示表单重复提交,我们可以给出相应的提示,或者其他的必要处理。
下面我们分别使用在网络延迟的情况下让用户有时间点击多次提交按钮、表单提交后用户点击【刷新】按钮、用户提交表单后,点击浏览器的【后退】按钮回退到表单页面后再次点击提交按钮,这三种方法对提交页面进行操作,结果如图11-20