为了防止用户在客户端重复提交表单,要分析从客户端和服务端对重复提交的表单就行处理,首先是客户端处理重复提交表单,使用JavaScript方法,第一种是只允许表单提交一次,后来的不能再提交,第二种是提交一次后按钮变成不可用,下面是代码的实现
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> <script type="text/javascript"> /* var isCommit = false; function doSubmit(){ if(! isCommit){ isCommit = true; return true; } else{ return false; } }*/ function doSubmit(){//使提交按钮再提交完成后不可用 var input = document.getElementById("submit"); input.disabled='disabled'; return true; } </script> </head> <body> <form action="/Web/servlet/DoFormServlet" method="post" onsubmit="return doSubmit()"> 用户名:<input type="text" name="username"><br> <input id="submit" type="submit" value="提交" > </form> </body> </html>
当然,这个随即数的产生不简单,首先使用单例设计模式,减少随机数产生的相似性概率,然后使用当前时间毫秒数加上一个随机数来进行,然后因为这样产生的随机数大小长度不等,所以进行md5编码后再进行BASE64编码,产生长度相等的而且字符都是键盘上可以识别的随机数,放到表单的隐藏域里面去。这个BASE64编码在网络传输中也有很好的作用,表单提交后,处理的Servlet根据放入到Session中的随机数来验证是不是重复提交,如果不是,就进行下面的比如放入到数据库等操作,如果是,则回复请求,说明表单重复提交。下面上代码
首先是产生表单的Servlet
package com.bird.form; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Random; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import sun.misc.BASE64Encoder; public class FormServlet extends HttpServlet { /** * 写给浏览器一个表单,并且防止多次重复提交而创建随机数 * @author Bird */ private static final long serialVersionUID = 1L; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //产生随机数(表单号 ) TokenProcessor tp = TokenProcessor.getInstance(); String token = tp.generateToken(); request.getSession().setAttribute("token", token); request.getRequestDispatcher("/form.jsp").forward(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } } class TokenProcessor{//令牌发生器 /** * 1.把构造方法私有 * 2.自己创建一个 * 3.对外暴露一个方法,允许获得创建的对象 */ private TokenProcessor(){} private static final TokenProcessor instance = new TokenProcessor(); public static TokenProcessor getInstance(){ return instance; } public String generateToken(){//获取唯一的表单码 String token = System.currentTimeMillis() + new Random().nextInt() + ""; try { MessageDigest md5 = MessageDigest.getInstance("md5"); byte[] md = md5.digest(token.getBytes()); //base64进行编码 BASE64Encoder encoder = new BASE64Encoder(); return encoder.encode(md); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } } }
<%@ 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> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <form action="/Web/servlet/DoFormServlet" method="post"> <input type="hidden" name="token" value="${token}"> 用户名:<input type="text" name="username"><br/> <input type="submit" value="提交"> </form> </body> </html>
package com.bird.form; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class DoFormServlet extends HttpServlet { /** * 处理表单的重复提交 * @author Bird */ private static final long serialVersionUID = 1L; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { boolean b = isTokenValue(request); if(!b){ System.out.println("请不要重复提交"); return; } request.getSession(false).removeAttribute("token"); System.out.println("向数据库中注入数据"); } private boolean isTokenValue(HttpServletRequest request) { String clinet_token = request.getParameter("token"); if(clinet_token == null){ return false; } String server_token = (String) request.getSession(false).getAttribute("token"); if(server_token == null){ return false; } if(!server_token.equals(clinet_token)){ return false; } return true; } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }