Java-Servlet知識總結

阿墩發表於2021-01-21


Servlet概述

為什麼要學習Servlet

Java Web的演變過程大概可以分為4個階段:

  • Servlet + jdbc + jsp
  • Spring + Struts2+ Hibernate(SSH)
  • Spring + SpringMVC + Mybatis(SSM)
  • 微服務階段

前兩個階段基本上可以說是歷史了,當今Spring家族一統天下。

現在實際開發中很少直接使用Servlet了,但是各個框架的底層還是大量使用了Servlet,學習Servlet對後續各個框架的理解和學習都很有幫助。

什麼是 Servlet

Servlet 是執行在 Web 伺服器或應用伺服器上的程式,它是作為來自 Web 瀏覽器或其他 HTTP 客戶端的請求和 HTTP 伺服器上的資料庫或應用程式之間的中間層。

Servlet其實就是一個遵循Servlet開發的java類。Serlvet是由伺服器呼叫的,執行在伺服器端。

Servlet帶給我們最大的作用就是能夠處理瀏覽器帶來HTTP請求,並返回一個響應給瀏覽器,從而實現瀏覽器和伺服器的互動

工作流程

  • Tomcat將瀏覽器提交的請求封裝成HttpServletRequest物件,同時將輸出流封裝成HttpServletResponse物件

  • Tomcat把request、response作為引數,呼叫Servlet的相應方法,例如doGet(request, response)等

  • Servlet中主要處理業務邏輯


生命週期

在 Web 容器中,Servlet 主要經歷 4 個階段,如下圖:
Servlet 生命週期

  1. 載入Servlet。當Tomcat第一次訪問Servlet的時候,Tomcat會負責建立Servlet的例項
  2. 初始化。當Servlet被例項化後,Tomcat會呼叫init()方法初始化這個物件
  3. 處理服務。當瀏覽器訪問Servlet的時候,Servlet 會呼叫service()方法處理請求
  4. 銷燬。當Tomcat關閉時或者檢測到Servlet要從Tomcat刪除的時候會自動呼叫destroy()方法讓該例項釋放掉所佔的資源。一個Servlet如果長時間不被使用的話,也會被Tomcat自動銷燬
  5. 解除安裝。當Servlet呼叫完destroy()方法後,等待垃圾回收。

如果有需要再次使用這個Servlet,會重新呼叫init()方法進行初始化操作

只要訪問Servlet,service()就會被呼叫。init()只有第一次訪問Servlet的時候才會被呼叫。

destroy()只有在Tomcat關閉的時候才會被呼叫。


處理請求的方法

Servlet 即實現了 Servlet 介面 的類,實現 Servlet 介面 的時候,需要實現5個方法

public interface Servlet {
    void init(ServletConfig var1) throws ServletException;

    ServletConfig getServletConfig();

    void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

    String getServletInfo();

    void destroy();
}

為了方便使用可以直接繼承 HttpServlet 類,該類已經預設實現了 Servlet 介面中的所有方法。

在編寫 Servlet 的時候,只需要重寫你需要的方法就好了。

並且該類還在原有 Servlet 介面上新增了一些與 HTTP 協議處理相關的方法。

  • Servlet 處理請求的方法一共有三種:
    • 實現 service() 方法
    • 重寫 doGet()
    • 重寫 doPost()

HttpServletRequest 和 HttpServletResponse

對於每次訪問請求,Servlet引擎都會建立一個新的HttpServletRequest請求物件和一個新的HttpServletResponse響應物件,即 request 和 response 物件。

HttpServletRequest 常用方法

  • String getContextPath()
    獲取上下文路徑
  • String getHeader(String headName)
    根據指定的請求頭獲取對應的請求頭的值.
  • String getRequestURI()
    返回當期請求的資源名稱. 上下文路徑/資源名
  • StringBuffer getRequestURL()
    返回瀏覽器位址列的內容
  • String getRemoteAddr()
    返回請求伺服器的客戶端的IP

獲取請求引數的方法:

  • String getParameter(String name)
    根據引數名稱,獲取對應引數的值.
  • String[] getParameterValues(String name)
    根據引數名稱,獲取該引數的多個值.
  • Enumeration getParameterNames()
    獲取所有請求引數的名字
  • Map<String,String[]> getParameterMap()
    返回請求引數組成的Map集合.

HttpServletResponse 常用方法

  • OutputStream getOutputStream():
    獲取位元組輸出流:檔案下載

  • Writer getWriter()
    獲取字元輸出流:輸出內容

  • resp.setContentType("text/html;charset=utf-8")

    設定檔案輸出的編碼格式和內容型別

  • resp.sendRedirect()

    302重定向,臨時跳轉

    301要使用另外的手段

Servlet 是單例的

解釋

瀏覽器多次對Servlet的請求,一般情況下,伺服器只建立一個Servlet物件,也就是說,Servlet物件一旦建立了,就會駐留在記憶體中,為後續的請求做服務,直到伺服器關閉。

每次訪問請求物件和響應物件都是新的

對於每次訪問請求,Servlet引擎都會建立一個新的HttpServletRequest請求物件和一個新的HttpServletResponse響應物件,然後將這兩個物件作為引數傳遞給它呼叫的Servlet的service()方法,service()方法再根據請求方式分別呼叫其他方法。

執行緒安全問題

當多個使用者訪問Servlet的時候,伺服器會為每個使用者建立一個執行緒。當多個使用者併發訪問Servlet共享資源的時候就會出現執行緒安全問題。

原則

  1. 如果一個變數需要多個使用者共享,則應當在訪問該變數的時候,需要加鎖
  2. 如果一個變數不需要共享,直接在 doGet() 或者 doPost()定義,這樣不會存線上程安全問題

通過註解配置 Servlet

在之前的開發工作中,每次編寫一個Servlet都需要在web.xml檔案中進行配置

<servlet>
    <servlet-name>ActionServlet</servlet-name>
    <servlet-class>com.web.controller.ActionServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>ActionServlet</servlet-name>
    <url-pattern>/servlet/ActionServlet</url-pattern>
</servlet-mapping>

而當一個專案中存在很多 Servlet,那麼配置檔案就會變得很亂很大,在 Servlet 3.0 推出之後,我們可以使用註解來配置 Servlet

@WebServlet(name = "ActionServlet", urlPatterns = "/servlet/ActionServlet")

Web 元件之間的跳轉方式

請求轉發(forward)

又叫做直接轉發方式,客戶端和瀏覽器只發出一次請求,Servlet、HTML、JSP或其它資訊資源,由第二個資訊資源響應該請求,在請求物件request中,儲存的物件對於每個資訊資源是共享的。

比如:從 AServlet 請求轉發到 BServlet

img

  • 語法:
request.getRequestDispatcher(path).forward(request, response);

引數:path,要跳轉到的資源路徑:上下文路徑 / 資源路徑

  • 特點:
    • 位址列中的地址不變
    • 只有一個請求
    • 資源是共享的
    • 可以訪問 WEB-INF 中的資源
    • 請求轉發不能跨域訪問

URl 重定向(redirect)

又叫做間接轉發方式(Redirect)實際是兩次HTTP請求,伺服器端在響應第一次請求的時候,讓瀏覽器再向另外一個URL發出請求,從而達到轉發的目的。

比如:從AServlet重定向到BServlet

img

  • 語法:
response.sendRedirect(String location);

引數:location,轉發到的資源路徑

  • 特點:
    • 位址列中的地址【會】發生改變
    • 有兩個請求
    • 在兩個 Servlet 中不可以共享請求中的資料
    • 最終的響應由BServlet來決定,和 AServlet 沒有關係
    • 不可以訪問 WEB-INF 中的資源
    • 請求轉發可以跨域訪問

參考