转载

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

  1.  html:form action="myAction.do" method="post"   
  2.  onsubmit="getElById('submitInput').disabled = true; return true;"    
  3.  html:image styleId="submitInput" src="images/ok_b.gif" border="0" /    
  4.  /html:form 

三.在JSP入门阶段也要注意善于利用STRUTS的同步令牌机制 
 
利用同步令牌(Token)机制来解决Web应用中重复Form表单提交的问题,Struts也给出了一个参考实现。

基本原理: 

服务器端在处理到达的请求之前,会将请求中包含的令牌值与保存在当前用户会话中的令牌值进行比较,看是否匹配。在处理完该请求后,且在答复发送给客户端之前,将会产生一个新的令牌,该令牌除传给客户端以外,也会将用户会话中保存的旧的令牌进行替换。这样如果用户回退到刚才的提交页面并再次提交的话,客户端传过来的令牌就和服务器端的令牌不一致,从而有效地防止了重复提交的发生。 

  1.  if (isTokenValid(request, true)) {   
  2.  // your code here   
  3.  return mapping.findForward("success");   
  4. } else {   
  5.  saveToken(request);   
  6.  return mapping.findForward("submitagain");   
  7. }   

STRUTS根据用户会话ID和当前系统时间来生成一个唯一(对于每个会话)令牌的,具体实现可以参考TokenProcessor类中的generateToken()方法。

1. //验证事务控制令牌,html:form 会自动根据session中标识生成一个隐含input代表令牌,防止两次提交

2. 在action中: 

  1.  //input type="hidden" name="org.apache.struts.taglib.html.TOKEN"   
  2.  // value="6aa35341f25184fd996c4c918255c3ae"   
  3.  if (!isTokenValid(request))   
  4.  errors.add(ActionErrors.GLOBAL_ERROR,   
  5.  new ActionError("error.transaction.token"));   
  6.  resetToken(request); //删除session中的令牌  

3. action有这样的一个方法生成令牌 

  1. protected String generateToken(HttpServletRequest request) {   
  2.  HttpSession session = request.getSession();   
  3.  try {   
  4.  byte id[] = session.getId().getBytes();   
  5.  byte now[] =   
  6.  new Long(System.currentTimeMillis()).toString().getBytes();   
  7.  MessageDigest md = MessageDigest.getInstance("MD5");   
  8.  md.update(id);   
  9.  md.update(now);   
  10.  return (toHex(md.digest()));   
  11.  } catch (IllegalStateException e) {   
  12.  return (null);   
  13.  } catch (NoSuchAlgorithmException e) {   
  14.  return (null);   
  15.  }   
  16.  }  


在更新的时候防止表单按钮重复点击,主要是用Session来做判断

四.在JSP入门时还要掌握页面方式

  1. input type="hidden " name=" % =com.lims.util.SynchroToken.TOKEN_NAME% " value =" %= com.lims.util.SynchroToken.getToken(request)%"     
  2.  
  3. SynchroToken.java  
  4. package com.lims.util;  
  5. import org.apache.struts.util.*;  
  6. import javax.servlet.http.*;  
  7. import javax.servlet.jsp.*;  
  8. import org.apache.struts.action.*;  
  9. /**  
  10.   * pTitle: SynchroToken /p  
  11.   * pDescription: /p  
  12.   * pCopyright: Copyright (c) 2004/p  
  13.   * pCompany: NetStar/p  
  14.   * @author Jstar  
  15.   * @version 1.0  
  16.   * Created in 2004/04/21  
  17.   */  
  18. public class SynchroToken{  
  19.  public final static java.lang.String TOKEN_NAME = "_token";  
  20.  public static boolean checkToken (HttpServletRequest request){  
  21.    boolean isEqual = false;  
  22.    HttpSession session = request.getSession ();  
  23.    String formToken = request.getParameter (TOKEN_NAME);  
  24.    String sessionToken = (String)session.getAttribute (TOKEN_NAME);  
  25.    System.out.println ("formToken: " + formToken + " sessionToken: " +  
  26.                        sessionToken);  
  27.    if (formToken != null && sessionToken == null){  
  28.      session.setAttribute (TOKEN_NAME, formToken);  
  29.      isEqual = true;  
  30.    }  
  31.    return isEqual;  
  32.  }  
  33.  /**  
  34.   * Insert the method's description here.  
  35.   * Creation date: (4/19/2004 3:23:25 PM)  
  36.   * @return java.lang.String  
  37.   * @param request javax.servlet.http.HttpServletRequest  
  38.   */  
  39.  public static String getToken (HttpServletRequest request){  
  40.    String token = "" + System.currentTimeMillis ();  
  41.    HttpSession session = request.getSession ();  
  42.    if (session != null){  
  43.      session.removeAttribute (TOKEN_NAME);  
  44.    }  
  45.    return token;z  
  46.  }  
  47.  /**  
  48.   * Insert the method's description here.  
  49.   * Creation date: (4/19/2004 3:24:10 PM)  
  50.   * @return java.lang.String  
  51.   */  
  52.  final static java.lang.String getTOKEN_NAME (){  
  53.    return TOKEN_NAME;  
  54.  }  
  55.  public static String message (PageContext pageContext, String key) throws  
  56.      JspException{  
  57.    return RequestUtils.message (pageContext, null, null, key);  
  58.  }  
  59. }   
  60.  

五.也可以通过添加中转页面的方式

对于JSP入门的角度讲,可以通过添加中转页面的方式,这样做虽然在视觉上不是很好,页面间显繁琐,但是这是有效地避免Form表单重复提交的好方式。


正文到此结束
Loading...