Servlet 與 Tomcat

最後更新: 2025-07-31 23:33:22 +0800 +0800
tags: Java | Servlet | Tomcat
原文以英文撰寫。您正在閱讀AI翻譯版本。

Jakarta Servlet API 定義伺服器端的請求與回應模型。Apache Tomcat 實作該 API,並提供 Catalina Servlet 容器、HTTP 與 AJP 連接器、工作階段管理、部署與操作工具。Tomcat 11 實作 Jakarta Servlet 6.1 並需要 Java 17;匯入 javax.servlet.* 的舊應用程式需要遷移至 jakarta.servlet.* 命名空間,或使用較舊的相容容器。

Web 應用程式配置 #

可部署的 Web 應用程式可以是展開的目錄或 WAR 封存:

text
orders.war
|-- index.html
`-- WEB-INF
    |-- web.xml
    |-- classes/com/example/OrdersServlet.class
    `-- lib/orders-domain.jar

WEB-INF/ 下的資源無法由用戶端直接定址。WEB-INF/classes/ 包含應用程式類別與資源,而 WEB-INF/lib/ 包含相依 JAR。WEB-INF/web.xml 是部署描述元。Servlet 3.0 及更新版本也支援以註解註冊,以及透過 ServletContainerInitializer 程式化註冊,因此除非部署需要描述元中繼資料或排序,否則可以省略 web.xml。

映射與請求分派 #

Servlet 映射會從 URL 模式選取 Servlet。精確映射優先於最長路徑映射,其次是副檔名映射與預設 / 映射。Filter 可以在目標之前或之後包裝請求與回應,而監聽器會觀察內容、工作階段與請求生命週期事件。

分派具有不同的 DispatcherType 值:

  • REQUEST 代表原始容器分派。
  • FORWARD 在不往返用戶端的情況下轉移處理。
  • INCLUDE 插入另一個資源的輸出。
  • ERROR 呼叫已設定的錯誤處理。
  • ASYNC 繼續非同步請求。
java
request.getRequestDispatcher("/WEB-INF/views/order.jsp")
       .forward(request, response);

重新導向則傳送 3xx 回應,之後用戶端會開始新的請求。在一般分派期間,連接器剖析請求,Catalina 選取虛擬主機與 Web 內容,Filter chain 執行,接著由一個 Servlet 實例處理呼叫。容器會並行呼叫 Servlet;因此可變的實例欄位需要同步,或最好移除。

工作階段由 Cookie 或 URL 重寫識別。工作階段屬性可能由並行請求存取,不得視為僅限執行緒。非同步處理會釋放請求執行緒,但應用程式必須完成 AsyncContext,並保留任何必要的安全性或記錄內容。

Tomcat 的容器模型 #

org.apache.catalina.startup.Bootstrap 會啟動獨立安裝。catalina.home 指向共用的 Tomcat 二進位檔,而 catalina.base 指向實例的設定、記錄、暫存檔、工作目錄與已部署應用程式。因此多個實例可以共用一個安裝。

Catalina 組合這些元素:

  1. Server 擁有 Tomcat 實例。
  2. Service 將一或多個 Connector 與一個 Engine 建立關聯。
  3. Engine 將請求路由至 Host。
  4. Host 包含一或多個 Web 應用程式 Context。
  5. Wrapper 代表個別 Servlet。

連接器擁有協定處理與工作執行緒。阻塞的 Servlet 工作會佔用這些執行緒,因此連接器限制、下游逾時與應用程式執行器限制必須構成單一容量規劃。

類別載入器與關閉 #

Tomcat 分隔 bootstrap、system、common 與每個 Web 應用程式的類別載入器。Web 應用程式可以看到自己的 WEB-INF/classes 與 WEB-INF/lib,但看不到其他應用程式的類別。Tomcat 的 Web 載入器對應用程式類別使用 local-first 查詢,但對 Java、Jakarta Servlet 與容器實作 API 強制委派。WEB-INF/lib 中重複的 API JAR 不會覆寫容器 API,且可能造成連結失敗。

若要正常關閉,停止接受新流量,讓執行中的工作在期限內完成,然後停止 Server。Servlet 內容監聽器與受管理資源會收到關閉回呼,但應用程式建立的執行器與執行緒仍需要明確終止。工作階段持久化取決於已設定的管理員,不得假設重新啟動後仍然存在。

主要參考資料 #

評論

在 GitHub 上閱讀或評論(發表評論需要登入)