JavaWeb中HttpSession中表单的重复提交示例

  

表单的重复提交

  
      <李>重复提交的情况:李   
  

①。在表单提交到一个Servlet,而Servlet又通过请求转发的方式响应了一个JSP (HTML)页面,此时地址栏还保留着Servlet的那个路径,在响应页面点击“刷”新。

  

②。在响应页面没有到达时,重复点击”提交按钮”

  

③。点击返回,再点击提交

  
      <李>不是重复提交的情况:点击“返回”,“刷”新原表单页面,再点击提交。   <李>如何避免表单的重复提交:在表单中做一个标记,提交到Servlet时,检查标记是否存在且和预定义的标记一样,若一致,则受理请求,并销毁标记,若不一致或没有标记,则直接响应提示信息:“重复提交”   
  

①仅提供一个隐藏域不行:& lt;输入类型=耙亍钡拿?傲钆啤眝alue=" https://www.yisu.com/zixun/lsy "在

  

②把标记放在请求中,行不,通表单页面刷新后,请求已经被销毁,再提交表单是一个新的请求的。

  

③把标记放在会话中,可以

  

1。在原表单页面,生成一个随机值标记
  2. 在原表单页面,把令牌值放入会话属性中

  

3。在原表单页面,把令牌值放入到隐藏域

  

4。在目标的Servlet中:获取会话和隐藏域中的令牌值

  

比较两个值是否一致,受理请求,且把会话域中属的标记性清除,若不一致,则直接响应提示页面:“重复提交”

  

我们可以通过Struts1中写好的类TokenProcessor来重构代码,面向组件编程

        包com.lsy.javaweb;   进口javax.servlet.http.HttpServletRequest;   进口javax.servlet.http.HttpSession;   进口java.security.MessageDigest;   进口java.security.NoSuchAlgorithmException;   公开课TokenProcessor {   私有静态最终字符串TOKEN_KEY=癟OKEN_KEY”;   私有静态最终字符串TRANSACTION_TOKEN_KEY=癟RANSACTION_TOKEN_KEY”;/* *   *这个类的单个实例。   */私有静态TokenProcessor实例=new TokenProcessor ();/* *   *最近使用的时间戳来生成一个令牌的值。   */私人很久以前;/* *   *保护TokenProcessor构造函数。使用   * TokenProcessor.getInstance()来获取处理器的引用。   */保护TokenProcessor () {   超级();   }/* *   *获取这个类的单个实例。   */公共静态TokenProcessor getInstance () {   返回实例;   }/* *   * & lt; p>   *返回& lt; code> true</code>如果有一个令牌存储在事务   *用户的当前会话,提交作为请求参数的值   *这个动作匹配。返回& lt; code> false</code>在任何的   *下列情形之一:   * & lt;/p>   *   * & lt; ul>   *   * & lt; li>没有会话与这request   *   * & lt; li>没有事务标记保存在session   *   * & lt; li>没有事务令牌作为一个请求parameter   *   * & lt; li>包括事务令牌值不匹配交易   在用户的session< *标记;/li>   *   * & lt;/ul>   *   * @param请求   * servlet请求我们处理   */公共同步布尔isTokenValid (HttpServletRequest请求){   返回。isTokenValid(请求,假);   }/* *   *返回& lt; code> true</code>如果有一个令牌存储在事务   *用户的当前会话,提交作为请求参数的值   *这个动作匹配。返回& lt; code> false</code>   *   * & lt; ul>   *   * & lt; li>没有会话与这request   * & lt; li>没有事务标记保存在session   *   * & lt; li>没有事务令牌作为一个请求parameter   *   * & lt; li>包括事务令牌值不匹配交易   在用户的session< *标记;/li>   *   * & lt;/ul>   *   * @param请求   * servlet请求我们处理   * @param重置   *我们应该重置令牌在检查这# 63;   */公共同步布尔isTokenValid (HttpServletRequest请求,布尔重置){//获取当前会话的请求   HttpSession会话=request.getSession(假);   如果(会话==null) {   返回错误;   }//检索事务从这个会话令牌,和//重置请求   字符串保存=(字符串)session.getAttribute (TRANSACTION_TOKEN_KEY);   如果(救了==null) {   返回错误;   }   如果(重置){   this.resetToken(请求);   }//检索事务令牌包含在此请求   字符串标记=request.getParameter (TOKEN_KEY);   如果令牌==null) {   返回错误;   }   返回saved.equals(令牌);   }/* *   *重置保存事务令牌在用户的会话。这表明   *事务标记检查不需要在下一个请求   *提交。   *   * @param请求   * servlet请求我们处理   */公共同步空白resetToken (HttpServletRequest请求){   HttpSession会话=request.getSession(假);   如果(会话==null) {   返回;   }   session.removeAttribute (TRANSACTION_TOKEN_KEY);   }/* *   *新事务标记保存在用户的当前会话,创建一个   *新会话,如果必要的。   *   * @param请求   * servlet请求我们处理   */公共字符串saveToken同步(HttpServletRequest请求){   HttpSession会话=request.getSession ();   字符串标记=generateToken(请求);   如果(令牌!=null) {   会话。setAttribute (TRANSACTION_TOKEN_KEY,令牌);   }   返回标记;   }/* *   *生成一个新的事务标记,用于执行一个   *请求一个特定的事务。   *   * @param请求   *我们正在处理的请求   */公共字符串generateToken同步(HttpServletRequest请求){   HttpSession会话=request.getSession ();   返回generateToken (session.getId ());   }/* *   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null   null

JavaWeb中HttpSession中表单的重复提交示例