JSP入门之避免Form表单重复提交的几种议案
对于JSP 入门的初级的学习者表单的提交是一个非常困扰的问题,那么如何避免Form 表单多次提交呢?可以从以下的几个方面入手:
一. 对于初学JSP 可以先通过Javascript 中设置
设置一个变量,只允许表单提交一次。
1. ﹤ script language = "javascript" ﹥
2. var checkSubmitFlg = false ;
3. function checkSubmit() {
4. if ( checkSubmitFlg == true) {
5. return false;
6. }
7. checkSubmitFlg = true ;
8. return true;
9. }
10. document.ondblclick = function docondblclick() {
11. window.event.returnValue = false ;
12. }
13. document.onclick = function doconclick() {
14. if (checkSubmitFlg) {
15. window.event.returnValue = false ;
16. }
17. }
18. ﹤ /script ﹥
19.
20. ﹤ html:form action = "myAction.do" method = "post" onsubmit = "return checkSubmit();" ﹥
二. 对于JSP 人门还要掌握Javascript 的另一设置
将表单提交按钮或者image 置为disable
21. ﹤ html:form action = "myAction.do" method = "post"
22. onsubmit = "getElById('submitInput').disabled = true; return true;" ﹥
23. ﹤ html:image styleId = "submitInput" src = "images/ok_b.gif" border = "0" / ﹥
24. ﹤ /html:form ﹥
三.
在JSP
入门阶段也要注意善于利用STRUTS
的同步令牌机制
利用同步令牌(Token
)机制来解决Web
应用中重复Form
表单提交的问题,Struts
也给出了一个参考实现。
基本原理:
服务器端在处理到达的请求之前,会将请求中包含的令牌值与保存在当前用户会话中的令牌值进行比较,看是否匹配。在处理完该请求后,且在答复发送给客户端之前,将会产生一个新的令牌,该令牌除传给客户端以外,也会将用户会话中保存的旧的令牌进行替换。这样如果用户回退到刚才的提交页面并再次提交的话,客户端传过来的令牌就和服务器端的令牌不一致,从而有效地防止了重复提交的发生。
25. if (isTokenValid(request, true)) {
26. // your code here
27. return mapping.findForward("success");
28. } else {
29. saveToken(request);
30. return mapping.findForward("submitagain");
31. }
STRUTS 根据用户会话ID 和当前系统时间来生成一个唯一(对于每个会话)令牌的,具体实现可以参考TokenProcessor 类中的generateToken() 方法。
1. // 验证事务控制令牌, ﹤html:form ﹥会自动根据session 中标识生成一个隐含input 代表令牌,防止两次提交
2. 在action 中:
32. // ﹤ input type = "hidden" name = "org.apache.struts.taglib.html.TOKEN"
33. // value = "6aa35341f25184fd996c4c918255c3ae" ﹥
34. if (!isTokenValid(request))
35. errors.add(ActionErrors.GLOBAL_ERROR,
36. new ActionError("error.transaction.token"));
37. resetToken(request); // 删除 session 中的令牌
3. action 有这样的一个方法生成令牌
38. protected String generateToken(HttpServletRequest request) {
39. HttpSession session = request .getSession();
40. try {
41. byte id[] = session.getId().getBytes();
42. byte now[] =
43. new Long(System.currentTimeMillis()).toString().getBytes();
44. MessageDigest md = MessageDigest .getInstance("MD5");
45. md.update(id);
46. md.update(now);
47. return (toHex(md.digest()));
48. } catch (IllegalStateException e) {
49. return (null);
50. } catch (NoSuchAlgorithmException e) {
51. return (null);
52. }
53. }
在更新的时候防止表单按钮重复点击,主要是用Session
来做判断
四. 在JSP 入门时还要掌握页面方式
54. ﹤ input type = "hidden " name = " ﹤ % =com.lims.util.SynchroToken.TOKEN_NAME% ﹥ " value = " ﹤ %= com.lims.util.SynchroToken.getToken(request)% ﹥ " ﹥
55.
56. SynchroToken.java
57. package com.lims.util;
58. import org.apache.struts.util.*;
59. import javax.servlet.http.*;
60. import javax.servlet.jsp.*;
61. import org.apache.struts.action.*;
62. /**
63. * ﹤ p ﹥ Title: SynchroToken ﹤ /p ﹥
64. * ﹤ p ﹥ Description: ﹤ /p ﹥
65. * ﹤ p ﹥ Copyright: Copyright (c) 2004 ﹤ /p ﹥
66. * ﹤ p ﹥ Company: NetStar ﹤ /p ﹥
67. * @author Jstar
68. * @version 1.0
69. * Created in 2004/04/21
70. */
71. public class SynchroToken{
72. public final static java.lang.String TOKEN_NAME = "_token" ;
73. public static boolean checkToken (HttpServletRequest request){
74. boolean isEqual = false ;
75. HttpSession session = request .getSession ();
76. String formToken = request .getParameter (TOKEN_NAME);
77. String sessionToken = (String)session.getAttribute (TOKEN_NAME);
78. System.out.println ("formToken: " + formToken + " sessionToken: " +
79. sessionToken);
80. if (formToken != null && sessionToken == null){
81. session.setAttribute (TOKEN_NAME, formToken);
82. isEqual = true ;
83. }
84. return isEqual;
85. }
86. /**
87. * Insert the method's description here.
88. * Creation date: (4/19/2004 3:23:25 PM)
89. * @return java.lang.String
90. * @param request javax.servlet.http.HttpServletRequest
91. */
92. public static String getToken (HttpServletRequest request){
93. String token = "" + System.currentTimeMillis ();
94. HttpSession session = request .getSession ();
95. if (session != null){
96. session.removeAttribute (TOKEN_NAME);
97. }
98. return token;z
99. }
100. /**
101. * Insert the method's description here.
102. * Creation date: (4/19/2004 3:24:10 PM)
103. * @return java.lang.String
104. */
105. final static java.lang.String getTOKEN_NAME (){
106. return TOKEN_NAME;
107. }
108. public static String message (PageContext pageContext, String key) throws
109. JspException{
110. return RequestUtils.message (pageContext, null, null, key);
111. }
112. }
113.
五. 也可以通过添加中转页面的方式
对于JSP 入门的角度讲,可以通过添加中转页面的方式,这样做虽然在视觉上不是很好,页面间显繁琐,但是这是有效地避免Form 表单重复提交的好方式。