最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaWeb中HttpSession中表單的重復(fù)提交示例

 更新時(shí)間:2017年03月01日 13:59:25   作者:http://blog.csdn.net/qq_24942951/article/details/58606050  
這篇文章主要介紹了JavaWeb中HttpSession中表單的重復(fù)提交,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下

表單的重復(fù)提交

  • 重復(fù)提交的情況:

①. 在表單提交到一個(gè) Servlet,而 Servlet 又通過(guò)請(qǐng)求轉(zhuǎn)發(fā)的方式響應(yīng)了一個(gè) JSP(HTML)頁(yè)面,此時(shí)地址欄還保留著 Servlet 的那個(gè)路徑,在響應(yīng)頁(yè)面點(diǎn)擊 “刷新”。

②. 在響應(yīng)頁(yè)面沒(méi)有到達(dá)時(shí),重復(fù)點(diǎn)擊 “提交按鈕”

③. 點(diǎn)擊返回,再點(diǎn)擊提交

  • 不是重復(fù)提交的情況:點(diǎn)擊 “返回”,“刷新” 原表單頁(yè)面,再點(diǎn)擊提交。
  • 如何避免表單的重復(fù)提交:在表單中做一個(gè)標(biāo)記,提交到 Servlet 時(shí),檢查標(biāo)記是否存在且和預(yù)定義的標(biāo)記一樣,若一致,則受理請(qǐng)求,并銷毀標(biāo)記,若不一致或沒(méi)有標(biāo)記,則直接響應(yīng)提示信息:“重復(fù)提交”

①僅提供一個(gè)隱藏域不行:<input type="hidden" name="token" value="lsy">

②把標(biāo)記放在 Request 中 , 行不通,表單頁(yè)面刷新后,request 已經(jīng)被銷毀,再提交表單是一個(gè)新的 request 的。

③把標(biāo)記放在 Session 中,可以

1. 在原表單頁(yè)面,生成一個(gè)隨機(jī)值 token
2. 在原表單頁(yè)面,把 token 值放入 session 屬性中

3. 在原表單頁(yè)面,把 token 值放入到隱藏域

4. 在目標(biāo)的 Servlet 中:獲取 session 和隱藏域中的 token 值

比較兩個(gè)值是否一致,受理請(qǐng)求,且把 session 域中的 token 屬性清除,若不一致,則直接響應(yīng)提示頁(yè)面:“重復(fù)提交”

我們可以通過(guò) Struts1 中寫好的類 TokenProcessor 來(lái)重構(gòu)代碼, 面向組件編程

package com.lsy.javaweb;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class TokenProcessor {
  private static final String TOKEN_KEY = "TOKEN_KEY";
  private static final String TRANSACTION_TOKEN_KEY = "TRANSACTION_TOKEN_KEY";
  /**
   * The singleton instance of this class.
   */
  private static TokenProcessor instance = new TokenProcessor();
  /**
   * The timestamp used most recently to generate a token value.
   */
  private long previous;
  /**
   * Protected constructor for TokenProcessor. Use
   * TokenProcessor.getInstance() to obtain a reference to the processor.
   */
  protected TokenProcessor() {
    super();
  }
  /**
   * Retrieves the singleton instance of this class.
   */
  public static TokenProcessor getInstance() {
    return instance;
  }
  /**
   * <p>
   * Return <code>true</code> if there is a transaction token stored in the
   * user's current session, and the value submitted as a request parameter
   * with this action matches it. Returns <code>false</code> under any of the
   * following circumstances:
   * </p>
   *
   * <ul>
   *
   * <li>No session associated with this request</li>
   *
   * <li>No transaction token saved in the session</li>
   *
   * <li>No transaction token included as a request parameter</li>
   *
   * <li>The included transaction token value does not match the transaction
   * token in the user's session</li>
   *
   * </ul>
   *
   * @param request
   *      The servlet request we are processing
   */
  public synchronized boolean isTokenValid(HttpServletRequest request) {
    return this.isTokenValid(request, false);
  }
  /**
   * Return <code>true</code> if there is a transaction token stored in the
   * user's current session, and the value submitted as a request parameter
   * with this action matches it. Returns <code>false</code>
   *
   * <ul>
   *
   * <li>No session associated with this request</li>
   * <li>No transaction token saved in the session</li>
   *
   * <li>No transaction token included as a request parameter</li>
   *
   * <li>The included transaction token value does not match the transaction
   * token in the user's session</li>
   *
   * </ul>
   *
   * @param request
   *      The servlet request we are processing
   * @param reset
   *      Should we reset the token after checking it?
   */
  public synchronized boolean isTokenValid(HttpServletRequest request, boolean reset) {
    // Retrieve the current session for this request
    HttpSession session = request.getSession(false);
    if (session == null) {
      return false;
    }
    // Retrieve the transaction token from this session, and
    // reset it if requested
    String saved = (String) session.getAttribute(TRANSACTION_TOKEN_KEY);
    if (saved == null) {
      return false;
    }
    if (reset) {
      this.resetToken(request);
    }
    // Retrieve the transaction token included in this request
    String token = request.getParameter(TOKEN_KEY);
    if (token == null) {
      return false;
    }
    return saved.equals(token);
  }
  /**
   * Reset the saved transaction token in the user's session. This indicates
   * that transactional token checking will not be needed on the next request
   * that is submitted.
   *
   * @param request
   *      The servlet request we are processing
   */
  public synchronized void resetToken(HttpServletRequest request) {
    HttpSession session = request.getSession(false);
    if (session == null) {
      return;
    }
    session.removeAttribute(TRANSACTION_TOKEN_KEY);
  }
  /**
   * Save a new transaction token in the user's current session, creating a
   * new session if necessary.
   *
   * @param request
   *      The servlet request we are processing
   */
  public synchronized String saveToken(HttpServletRequest request) {
    HttpSession session = request.getSession();
    String token = generateToken(request);
    if (token != null) {
      session.setAttribute(TRANSACTION_TOKEN_KEY, token);
    }
    return token;
  }
  /**
   * Generate a new transaction token, to be used for enforcing a single
   * request for a particular transaction.
   *
   * @param request
   *      The request we are processing
   */
  public synchronized String generateToken(HttpServletRequest request) {
    HttpSession session = request.getSession();
    return generateToken(session.getId());
  }
  /**
   * Generate a new transaction token, to be used for enforcing a single
   * request for a particular transaction.
   *
   * @param id
   *      a unique Identifier for the session or other context in which
   *      this token is to be used.
   */
  public synchronized String generateToken(String id) {
    try {
      long current = System.currentTimeMillis();
      if (current == previous) {
        current++;
      }
      previous = current;
      byte[] now = new Long(current).toString().getBytes();
      MessageDigest md = MessageDigest.getInstance("MD5");
      md.update(id.getBytes());
      md.update(now);
      return toHex(md.digest());
    } catch (NoSuchAlgorithmException e) {
      return null;
    }
  }
  /**
   * Convert a byte array to a String of hexadecimal digits and return it.
   *
   * @param buffer
   *      The byte array to be converted
   */
  private String toHex(byte[] buffer) {
    StringBuffer sb = new StringBuffer(buffer.length * 2);
    for (int i = 0; i < buffer.length; i++) {
      sb.append(Character.forDigit((buffer[i] & 0xf0) >> 4, 16));
      sb.append(Character.forDigit(buffer[i] & 0x0f, 16));
    }
    return sb.toString();
  }
}

以上所述是小編給大家介紹的JavaWeb中HttpSession中表單的重復(fù)提交示例,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

相關(guān)文章

  • java 解析user-agent 信息

    java 解析user-agent 信息

    這篇文章主要介紹了java 解析http user-agent的信息的相關(guān)資料,需要的朋友可以參考下
    2016-07-07
  • 解決idea 暫存文件或idea切換分支代碼丟失的問(wèn)題

    解決idea 暫存文件或idea切換分支代碼丟失的問(wèn)題

    這篇文章主要介紹了解決idea 暫存文件或idea切換分支代碼丟失的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-02-02
  • Java行為型設(shè)計(jì)模式之策略模式詳解

    Java行為型設(shè)計(jì)模式之策略模式詳解

    策略模式屬于Java-設(shè)計(jì)模式中行為模式之一,該模式定義了一系列算法,并將每個(gè)算法封裝起來(lái),使它們可以相互替換。本文將通過(guò)示例詳細(xì)講解這一模式,需要的可以參考一下
    2022-11-11
  • SpringBoot文件訪問(wèn)映射如何實(shí)現(xiàn)

    SpringBoot文件訪問(wèn)映射如何實(shí)現(xiàn)

    這篇文章主要介紹了SpringBoot文件訪問(wèn)映射如何實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • Java 根據(jù)網(wǎng)址查詢DNS/IP地址的方法

    Java 根據(jù)網(wǎng)址查詢DNS/IP地址的方法

    這篇文章主要介紹了Java 根據(jù)網(wǎng)址查詢DNS/IP地址的方法,具體實(shí)現(xiàn)代碼,大家參考下本文
    2017-12-12
  • Java switch case數(shù)據(jù)類型原理解析

    Java switch case數(shù)據(jù)類型原理解析

    這篇文章主要介紹了Java switch case數(shù)據(jù)類型原理解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-01-01
  • 關(guān)于Spring的@Autowired依賴注入常見(jiàn)錯(cuò)誤的總結(jié)

    關(guān)于Spring的@Autowired依賴注入常見(jiàn)錯(cuò)誤的總結(jié)

    有時(shí)我們會(huì)使用@Autowired自動(dòng)注入,同時(shí)也存在注入到集合、數(shù)組等復(fù)雜類型的場(chǎng)景。這都是方便寫 bug 的場(chǎng)景,本篇文章帶你了解Spring @Autowired依賴注入的坑
    2021-09-09
  • MyBatis-Plus簡(jiǎn)介和快速入門教程

    MyBatis-Plus簡(jiǎn)介和快速入門教程

    MyBatis-Plus是一個(gè)MyBatis的增強(qiáng)工具,在MyBatis的基礎(chǔ)上只做增強(qiáng)不做修改,為簡(jiǎn)化開(kāi)發(fā)、提高效率而生,本文給大家介紹MyBatis-Plus簡(jiǎn)介和快速入門教程,需要的朋友參考下吧
    2021-09-09
  • Java 中 getClass() 方法的使用與原理深入分析(對(duì)象類型信息)

    Java 中 getClass() 方法的使用與原理深入分析(對(duì)象類型信息)

    在 Java 編程中,getClass() 是一個(gè)非常重要的方法,它用于獲取對(duì)象的運(yùn)行時(shí)類信息,無(wú)論是調(diào)試代碼、反射操作,還是類型檢查,getClass() 都扮演著關(guān)鍵角色,本文將深入探討 getClass() 的使用方法、底層原理以及實(shí)際應(yīng)用場(chǎng)景,感興趣的朋友一起看看吧
    2024-12-12
  • idea中如何使用git進(jìn)行版本回退詳解

    idea中如何使用git進(jìn)行版本回退詳解

    工作中遇到git遠(yuǎn)程倉(cāng)庫(kù)需要回退到歷史版本的問(wèn)題,根據(jù)網(wǎng)上的搜索結(jié)果結(jié)合自己的實(shí)踐,下面這篇文章主要給大家介紹了關(guān)于idea中如何使用git進(jìn)行版本回退的相關(guān)資料,需要的朋友可以參考下
    2023-04-04

最新評(píng)論

高阳县| 政和县| 剑阁县| 鄂托克前旗| 临江市| 德江县| 调兵山市| 湘乡市| 龙川县| 玛纳斯县| 延边| 阜南县| 盱眙县| 五莲县| 淄博市| 阿拉善盟| 连山| 龙江县| 察雅县| 高唐县| 博客| 新龙县| 上高县| 安泽县| 苍溪县| 辽宁省| 涿州市| 海口市| 金寨县| 名山县| 顺平县| 新野县| 民丰县| 通海县| 巨鹿县| 启东市| 湘乡市| 改则县| 清河县| 金门县| 浦县|