誰再問Servlet的問題,我就親自上門來教學了

1. 概述

在這篇簡短的文章中,咱們將從概念上理解什麼是servletservlet 容器以及它們是如何工做的
同時,還能在請求、響應、會話對象、共享變量和多線程的上下文中看到它們的身影。
java

2. Servlets 和 它的容器

servletJEE 用於 web 開發經常使用的組件。它們基本上是運行在容器邊界內的Java程序。總的來講,它們負責接受請求,處理請求,並返回響應web

要使用它們,首先須要容器註冊 servlet ,不管是基於 JEE 仍是基於 Spring 的容器,均可以在啓動時接收它們。在開始時,容器經過調用 init() 方法來實例化 servlet
初始化完成後,servlet 就能夠接受傳入的請求。隨後,容器將這些請求定向到 servletservice 方法中進行處理。以後,它根據HTTP請求類型將請求進一步委託給適當的方法,例如 doGet()doPost()瀏覽器

使用 destroy(),容器會銷燬 servlet,而且再也不接受傳入的請求。咱們將這個 init-service-destroy 的循環稱爲 servlet 的生命週期。安全

如今咱們從容器的角度來看,好比 Apache TomcatJetty 在啓動時,建立一個 ServletContext 的對象,ServletContext 的任務是充當服務器或容器的內存,並記住與web應用程序相關聯的全部servlet、過濾器和偵聽器,如其 web.xml文件或等效註解。在容器中止以前,ServletContext 會一直保留它。服務器

無論怎麼說,servletload-on-startup 參數扮演重要的角色 。若是此參數的值大於零,則只有在啓動時服務器纔會對其進行初始化。若是未指定此參數,則在請求第一次命中 servlet時調用它的 init()
filecookie

3. Request, Response 和 Session

在上一節中,咱們討論了發送請求和接收響應,這基本上是任何CS應用程序的基礎。如今,咱們從servlet的角度來詳細瞭解它們。session

在這種狀況下,請求將由 HttpServletRequest 表示,響應將用 HttpServletResponse 表示。多線程

每當瀏覽器或curl命令等發送請求時,容器都會建立一個新的 HttpServletRequestHttpServletResponse 對象。而後將這些新對象傳遞給 servletservice方法。基於 HttpServletRequestmethod 屬性,此方法肯定應調用哪一個 doXXX方法。併發

除了有關方法的信息外,request對象還攜帶其餘信息,如頭、參數和主體。相似地,HttpServletResponse對象也攜帶頭、參數和主體——咱們能夠在 servletdoXXX 方法中設置它們。curl

這些對象的生命稍縱即逝。當客戶端得到響應時,服務器將標記用於垃圾回收的請求和響應對象。
那麼咱們如何在隨後的客戶端請求或鏈接之間保持一個狀態?答案就是 HttpSession

原理是將這些對象綁定到用戶會話,以便與特定用戶相關的信息能夠跨多個請求持久化。這一般是經過使用cookies的概念,使用 [JSESSIONID] 做爲給定會話的惟一標識符。咱們能夠在web.xml中指定會話的超時時長。

<session-config>
    <session-timeout>10</session-timeout>
</session-config>

以上配置表示,若是會話空閒了10分鐘,服務器將丟棄它。任何後續請求都將建立一個新的會話。

4. Servlets 共享數據

根據所需的範圍,servlet 能夠經過多種方式共享數據。

正如在前面的章節中提到的,不一樣的對象有不一樣的生命週期。HttpServletRequestHttpServletResponse 對象只存在於一個 servlet 調用之間。HttpSession只要它處於活動狀態而且沒有超時,它就會一直存在。

ServletContext的生命週期最長。它與Web應用程序一塊兒誕生,只有當應用程序自己關閉時纔會被銷燬。因爲servlet、filter 和 listener 實例與上下文綁定,因此只要web應用程序啓動並運行,它們也會一直存在。

所以,若是咱們的需求是在全部servlet之間共享數據,假設咱們要計算站點的訪問者數量,那麼咱們應該將變量放在 ServletContext 中。若是咱們須要在一個會話中共享數據,那麼咱們就把它保存在會話範圍內。在本例中,用戶名就是一個例子。

最後,還有與單個請求的數據相關的請求範圍,好比請求有效負載。

5. 處理多線程

多個HttpServletRequest 對象彼此共享 servlet,這樣每一個請求都使用它本身的 servlet 實例線程進行操做。

就線程安全而言,這實際上代表:咱們不該該將請求或會話範圍內的數據指定爲 servlet的實例變量。

例如,下面的代碼片斷:

public class ExampleThree extends HttpServlet {
    
    private String instanceMessage;

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException {
        String message = request.getParameter("message");
        instanceMessage = request.getParameter("message");
        request.setAttribute("text", message);
        request.setAttribute("unsafeText", instanceMessage);
        request.getRequestDispatcher("/jsp/ExampleThree.jsp").forward(request, response);
    }
}

在本例中,會話中的全部請求共享 instanceMessage,而 message對於給定的請求對象是惟一的。所以,在併發請求的狀況下,instanceMessage 中的數據可能不一致。

6. 總結

在本教程中,咱們探討了有關servlet的一些概念、它們的容器以及它們所圍繞的一些基本對象,以及 servlet 如何共享數據和多線程如何影響它們.

若是你以爲文章還不錯,記得關注公衆號: 鍋外的大佬
鍋外的大佬博客

相關文章
相關標籤/搜索