为了防止用户在客户端重复提交表单,要分析从客户端和服务端对重复提交的表单就行处理,首先是客户端处理重复提交表单,使用JavaScript方法,第一种是只允许表单提交一次,后来的不能再提交,第二种是提交一次后按钮变成不可用,下面是代码的实现
1 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
2 <html>
3 <head>
4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
5 <title>Insert title here</title>
6 <script type="text/javascript">
7 /*
8 var isCommit = false;
9 function doSubmit(){
10 if(! isCommit){
11 isCommit = true;
12 return true;
13 } else{
14 return false;
15 }
16 }*/
17 function doSubmit(){//使提交按钮再提交完成后不可用
18 var input = document.getElementById("submit");
19 input.disabled='disabled';
20 return true;
21 }
22 </script>
23
24
25 </head>
26 <body>
27 <form action="/Web/servlet/DoFormServlet" method="post" οnsubmit="return doSubmit()">
28 用户名:<input type="text" name="username"><br>
29 <input id="submit" type="submit" value="提交" >
30 </form>
31 </body>
32 </html>
但是仅仅在客户端进行处理是远远不够的,这叫只能防的了君子防不了小人,因为可以根据服务器的提交地址自己写一个表单或者去掉JavaScript代码进行自己的提交,这样仍旧无法阻止客户端的表单的重复提交,下面就需要在服务端做手脚,首先需要写一个Servlet用来产生表单,他的想法是产生一个唯一的Id ,通过随机数才产生,然后付到表单上,当表单提交的时候,根据验证这个ID号来判断时候是重复提交表单。
当然,这个随即数的产生不简单,首先使用单例设计模式,减少随机数产生的相似性概率,然后使用当前时间毫秒数加上一个随机数来进行,然后因为这样产生的随机数大小长度不等,所以进行md5编码后再进行BASE64编码,产生长度相等的而且字符都是键盘上可以识别的随机数,放到表单的隐藏域里面去。这个BASE64编码在网络传输中也有很好的作用,表单提交后,处理的Servlet根据放入到Session中的随机数来验证是不是重复提交,如果不是,就进行下面的比如放入到数据库等操作,如果是,则回复请求,说明表单重复提交。下面上代码
首先是产生表单的Servlet
[java] view plaincopyprint?
33 package com.bird.form;
34
35 import java.io.IOException;
36 import java.security.MessageDigest;
37 import java.security.NoSuchAlgorithmException;
38 import java.util.Random;
39
40 import javax.servlet.ServletException;
41 import javax.servlet.http.HttpServlet;
42 import javax.servlet.http.HttpServletRequest;
43 import javax.servlet.http.HttpServletResponse;
44
45 import sun.misc.BASE64Encoder;
46
47 public class FormServlet extends HttpServlet {
48
49 /**
50 * 写给浏览器一个表单,并且防止多次重复提交而创建随机数
51 * @author Bird
52 */
53 private static final long serialVersionUID = 1L;
54
55 public void doGet(HttpServletRequest request, HttpServletResponse response)
56 throws ServletException, IOException {
57 //产生随机数(表单号 )
58 TokenProcessor tp = TokenProcessor.getInstance();
59 String token = tp.generateToken();
60
61 request.getSession().setAttribute("token", token);
62
63 request.getRequestDispatcher("/form.jsp").forward(request, response);
64 }
65
66 public void doPost(HttpServletRequest request, HttpServletResponse response)
67 throws ServletException, IOException {
68 doGet(request, response);
69
70 }
71
72 }
73
74 class TokenProcessor{//令牌发生器
75 /**
76 * 1.把构造方法私有
77 * 2.自己创建一个
78 * 3.对外暴露一个方法,允许获得创建的对象
79 */
80
81 private TokenProcessor(){}
82
83 private static final TokenProcessor instance = new TokenProcessor();
84
85 public static TokenProcessor getInstance(){
86 return instance;
87 }
88
89 public String generateToken(){//获取唯一的表单码
90 String token = System.currentTimeMillis() + new Random().nextInt() + "";
91 try {
92 MessageDigest md5 = MessageDigest.getInstance("md5");
93 byte[] md = md5.digest(token.getBytes());
94
95 //base64进行编码
96 BASE64Encoder encoder = new BASE64Encoder();
97 return encoder.encode(md);
98 } catch (NoSuchAlgorithmException e) {
99 throw new RuntimeException(e);
100 }
101 }
102 }
然后是那个JSP页面
[java] view plaincopyprint?
103 <%@ page language="java" contentType="text/html; charset=UTF-8"
104 pageEncoding="UTF-8"%>
105 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
106 <html>
107 <head>
108 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
109 <title>Insert title here</title>
110 </head>
111 <body>
112 <form action="/Web/servlet/DoFormServlet" method="post">
113 <input type="hidden" name="token" value="${token}">
114 用户名:<input type="text" name="username"><br/>
115 <input type="submit" value="提交">
116 </form>
117 </body>
118 </html>
然后是处理提交请求的Servlt
[java] view plaincopyprint?
119 package com.bird.form;
120
121 import java.io.IOException;
122
123 import javax.servlet.ServletException;
124 import javax.servlet.http.HttpServlet;
125 import javax.servlet.http.HttpServletRequest;
126 import javax.servlet.http.HttpServletResponse;
127
128 public class DoFormServlet extends HttpServlet {
129
130 /**
131 * 处理表单的重复提交
132 * @author Bird
133 */
134 private static final long serialVersionUID = 1L;
135
136 public void doGet(HttpServletRequest request, HttpServletResponse response)
137 throws ServletException, IOException {
138 boolean b = isTokenValue(request);
139 if(!b){
140 System.out.println("请不要重复提交");
141 return;
142 }
143 request.getSession(false).removeAttribute("token");
144 System.out.println("向数据库中注入数据");
145 }
146
147 private boolean isTokenValue(HttpServletRequest request) {
148 String clinet_token = request.getParameter("token");
149 if(clinet_token == null){
150
151 return false;
152 }
153 String server_token = (String) request.getSession(false).getAttribute("token");
154 if(server_token == null){
155
156 return false;
157 }
158 if(!server_token.equals(clinet_token)){
159
160 return false;
161 }
162
163 return true;
164 }
165
166 public void doPost(HttpServletRequest request, HttpServletResponse response)
167 throws ServletException, IOException {
168 doGet(request, response);
169
170 }
171
172 }