Java Web高級編程(二)

来源:http://www.cnblogs.com/winterfells/archive/2017/12/10/8018306.html
-Advertisement-
Play Games

使用會話維持狀態 一、會話 為了實現關聯同一個用戶端的多個請求和這些請求之間數據的共用,需要用到會話,會話用於維持請求和請求之間的狀態。從伺服器的角度,當用戶的Web瀏覽器打開第一個鏈接到伺服器的套接字時請求就開始了,直到伺服器返回最後一個數據包並關閉鏈接是,該請求將結束。此時用戶瀏覽器和伺服器之間 ...


使用會話維持狀態

一、會話

為了實現關聯同一個用戶端的多個請求和這些請求之間數據的共用,需要用到會話,會話用於維持請求和請求之間的狀態。從伺服器的角度,當用戶的Web瀏覽器打開第一個鏈接到伺服器的套接字時請求就開始了,直到伺服器返回最後一個數據包並關閉鏈接是,該請求將結束。此時用戶瀏覽器和伺服器之間不再有任何的聯繫,當下一個鏈接開始時,無法將新的請求和之前的請求關聯起來。

維持狀態

最經典的例子就是線上購物網站需要用購物車來保證用戶和商品都能夠被保持。

記住用戶

這樣的例子是用戶論壇網站,在多個操作中,用戶只需要登錄一次。

啟動任務程式工作流

用戶在使用Web應用程式完成某個任務時,需要某種形式的工作流,比如新聞的發佈。

二、使用會話cookie和URL重寫。

會話是由伺服器或Web應用程式管理的某些文件、記憶體片段、對象或者容器,它包含了分配給它的各種不同數據。

通常會話被賦予一個隨機生成的字元串,稱為會話ID。第一次創建會話時,創建的會話ID會作為響應的一部分返回到用戶的瀏覽器中。接下來從該用戶瀏覽器發出的請求都將通過某種方式包含這個會話ID。當應用程式收到含有會話ID的請求時,它可以通過該ID將現有會話和當前請求關聯起來。

實現會話ID從伺服器返回到瀏覽器中的方法包括會話cookie和URL重寫。

會話cookie

這種技術也叫HTTP cookie。cookie是一種必要的通信機制,可以通過Set-Cookie響應頭在伺服器和瀏覽器中傳遞任意數據,並存儲在用戶電腦中,然後再通過請求頭Cookie從瀏覽器返回到伺服器中。cookie包含了功能變數名稱、路徑、過期日期或最大生命周期,安全標誌或只含有HTTP標誌。會話cookie的名字預設為JSESSIONID。

Domain將告訴瀏覽器應該將cookie發送到哪個功能變數名稱中,

Path則進一步將cookie限制在相對於域的某個特定的URL中,

Expries定義了cookie的絕對過期日期,

如果存在Secure特性,瀏覽器只會通過HTTPS發送cookie,進行加密傳輸,

HttpOnly將cookie限制在瀏覽器,避免JavaScript和flash。

URL中的會話ID

另一種傳輸會話ID的方式是通過URL,Web伺服器直到如何查找URL中包含會話ID的特定模式,不同的技術對如何在URL中內嵌和定位會話ID使用不同的策略。在Java EE中,會話ID被添加到URL的最後一個路徑段的舉證參數中,通過這種方式會分離開會話ID與查詢字元串的參數。例如:

http://www.example.com/supprot;JSESSIONID=NRxclGg2vG7kI4MdlLn?foo=bar

必須將會話ID內嵌在應用程式返回的所有URL中,包括頁面的鏈接、表單操作以及重定向。

HttpServletResponse介面定義了兩個重寫URL的方法:encodeURL和encodeRedirectURL,它們將在必要的時候把會話ID內嵌在URL中。

漏洞

複製粘貼錯誤,會話固定,跨站腳本和會話劫持,不安全的cookie

三、在會話中存儲數據

在部署描述符中配置會話:

    <session-config>
        <session-timeout>30</session-timeout>
        <cookie-config>
            <http-only>true</http-only>
        </cookie-config>
        <tracking-mode>COOKIE</tracking-mode>
    </session-config>

所有的<session-config>和<cookie-config>標簽都是可選的,至於標簽的作用可以另行查看。使用上述配置,會話超時時間為30min,只接受cookie用於會話追蹤,。

存儲,刪除和獲取數據:

在Servlet中創建map,可以使用該Map來進行數據的相關操作。

private final Map<Integer, String> products = new Hashtable<>();

    public StoreServlet()
    {
        this.products.put(1, "Sandpaper");
        this.products.put(2, "Nails");
        this.products.put(3, "Glue");
        this.products.put(4, "Paint");
        this.products.put(5, "Tape");
    }

1.doGet方法中的使用:

@Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException
    {
        String action = request.getParameter("action");
        if(action == null)
            action = "browse";

        switch(action)
        {
            case "addToCart":
                this.addToCart(request, response);
                break;

            case "emptyCart":
                this.emptyCart(request, response);
                break;

            case "viewCart":
                this.viewCart(request, response);
                break;

            case "browse":
            default:
                this.browse(request, response);
                break;
        }
    }

    private void addToCart(HttpServletRequest request,
                           HttpServletResponse response)
            throws ServletException, IOException
    {
        int productId;
        try
        {
            productId = Integer.parseInt(request.getParameter("productId"));
        }
        catch(Exception e)
        {
            response.sendRedirect("shop");
            return;
        }

        HttpSession session = request.getSession();
        if(session.getAttribute("cart") == null)
            session.setAttribute("cart", new Hashtable<Integer, Integer>());

        @SuppressWarnings("unchecked")
        Map<Integer, Integer> cart =
                (Map<Integer, Integer>)session.getAttribute("cart");
        if(!cart.containsKey(productId))
            cart.put(productId, 0);
        cart.put(productId, cart.get(productId) + 1);

        response.sendRedirect("shop?action=viewCart");
    }

    private void emptyCart(HttpServletRequest request,
                           HttpServletResponse response)
            throws ServletException, IOException
    {
        request.getSession().removeAttribute("cart");
        response.sendRedirect("shop?action=viewCart");
    }

    private void viewCart(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException
    {
        request.setAttribute("products", this.products);
        request.getRequestDispatcher("/WEB-INF/jsp/view/viewCart.jsp")
                .forward(request, response);
    }

    private void browse(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException
    {
        request.setAttribute("products", this.products);
        request.getRequestDispatcher("/WEB-INF/jsp/view/browse.jsp")
               .forward(request, response);
    }

四、將使用會話的用戶群集化

集群為應用程式增加了冗餘和可擴展性,經過正確配置的群集應用程式即使在遇到某些伺服器終止時也能夠正常運行,是指在執行日常維護工作時也可以正常處理用戶請求。管理員甚至可以升級應用程式,並保證應用程式不會終止對請求的處理。

Advanced Message Queuing Protocol(AMQP)、Java Message Service(JMS)、Microsoft Message Queuing(MSMQ)。

問題:會話一對象的方式存在於記憶體中,並且只存在於Web容器的單個實例中,來自同一個客戶端的兩個連續請求將會訪問不同的Web容器,而第一個容器分配的ID,第二個容器無法識別。

解決:使用粘滯會話:使負載均衡機制能夠感知到會話,並且總是將來自於同一會話的請求發送到相同的伺服器。(取決於負載均衡技術,比如負載均衡器在響應中添加他們自己的會話cookie,併在後學的請求中識別這些cookie)。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • ...
  • 基於資料庫的自動化生成工具,根據資料庫表結構自動生成JavaBean、自動生成MyBaits的Mapper映射配置文件、自動生成資料庫設計文檔、自動生成各種SQL等。支持MySQL、Oracle、SQLServce、PostgreSQL四種資料庫,支持Window、Linux、MacBook等多個... ...
  • 1、作用域public,private,protected,以及不寫時的區別 答: 區別如下: 2、Anonymous Inner Class (匿名內部類) 是否可以extends(繼承)其它類,是否可以implements(實現)interface(介面) 答: 匿名的內部類是沒有名字的內部類。 ...
  • 1. 列表list 1.1 切片# 定義一個list。list = [1, 2, 3, 4, 5] 從左往右讀取字元(預設步長為 1 )。如:list[-2:-1] # 返回一個list數據類型,[6]list[2] # 返回一個int數據類型, 3 從右往左讀取字元串(預設步長為 1 )。如:li ...
  • 在開發項目時,有時候需要用到上傳功能,比如頭像上傳等,其文件會保存到伺服器中。但是我發現在用eclipse做項目的過程中,每次重新部署項目,原來上傳的文件就會丟失。 其原因是因為每次項目修改後,eclipse會把我們放在工作空間workspace中的這個項目拷貝到伺服器下(如tomcat的webap ...
  • ...
  • 在學習有關java枚舉的時候,我們知道了所有的枚舉類型均是繼承自java.lang.Enum類的,且所有的枚舉常量均是該枚舉類型的一個對象,且對象名即為該枚舉常量的名稱。例子如下:源碼: 反編譯後的代碼: 在寫代碼的時候,由於輸入法切換的問題,發現枚舉常量的常量名稱居然是可以使用中文的。代碼如下: ...
  • 一、PTA實驗作業 題目1:查驗身份證 1. 本題PTA提交列表 2. 設計思路 3.代碼截圖 4.本題調試過程碰到問題及PTA提交列表情況說明。 部分正確 :將x改為大寫x 題目2:藏頭詩 1. 本題PTA提交列表 2. 設計思路 3.代碼截圖 4.本題調試過程碰到問題及PTA提交列表情況說明。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...