對於Java程式而言,JVM(Java Virtual Machine)是其作業系統,.java 編譯為 .class 檔案,.class 對於 JVM 而言,就是其可執行檔,你的 Java 程式基本上只認得一種作業系統,就是 JVM。
當你開始撰寫 Servlet/JSP 程式時,你必須開始接觸容器(Container)的概念,容器這個名詞也用在如 List
、Set
這類的 Collection
上,也就是用來持有、保存物件的群集(Collection)物件,不過,對於撰寫 Servlet/JSP 來說,容器的概念更為廣泛,在最基本的功能上,它不僅持有物件,還負責物件的生命周期與相關服務的連結。
在具體層面,容器說穿了,其實就是一個用 Java 寫的程式,運行於 JVM 之上,不同類型的容器會負責不同的工作,若以 Servlet/JSP 所運行的 Web 容器(Web Container)來說,也是一個 Java 寫的程式,想想看,HTTP 那些文字性的通訊協定,如何變成你寫的 Servlet/JSP 中可用的 Java 物件(如 HttpServletRequest
、HttpServletResponse
等),其實就是容器為你剖析與轉換。
在抽象層面,可以將 Web 容器視為你寫的 Servlet/JSP 的運行伺服器,是的!就如同 Java 程式僅認得 JVM 這個作業系統,Servlet/JSP 程式在抽象層面上,也僅認得 Web 容器這個概念上的 Web 伺服器,只要你寫的 Servlet/JSP 是符合 Web 容器的標準規範,你的 Servlet/JSP 就可以在各種不同廠商實作的 Web 容器上運行,而不用理會底層真正的 Web 伺服器。
當然,實際上還是要有個 Web 伺服器,所以回到實際層面,Web 容器是個 Java 寫的應用程式,可以成為實體 Web 伺服器程式的一部份,管理 Servlet 物件的生命週期,提供基於 HTTP 請求、回應的網路服務。
若以 Tomcat 為例,容器的角色位置可以用下圖來表示:
就如同 JVM 介於 Java 程式與實體作業系統之間,Web 容器是介於實體 Web 伺服器與 Servlet 之間,也正如你撰寫 Java 程式必須了解 JVM/JRE 與你的應用程式之間如何互動,你撰寫 Servlet/JSP 也必須知道容器如何與你的 Servlet/JSP 互動,如何管理 Servlet 等事實(JSP最後也是轉譯、編譯、載入為 Servlet,在容器的世界中,真正負責請求、回應的是 Servlet)。
一個請求/回應的基本例子是:
- 客戶端(大部份情況下是瀏覽器)對 Web 伺服器發出 HTTP 請求。
- Web 伺服器收到 HTTP 請求,將請求轉由 Web 容器處理,Web 容器會剖析 HTTP 請求內容,建立各種物件(像是
HttpServletRequest
、HttpServletResponse
、HttpSession
等)。 - Web 容器由請求的 URL 決定要使用哪個 Servlet 來處理請求(事先由開發人員定義)。
- Servlet 根據請求物件(
HttpServletRequest
)的資訊決定如何處理,透過回應物件(HttpServletResponse
)來建立回應。 - Web 容器與 Web 伺服器溝通,Web 伺服器將回應轉換為 HTTP 回應並傳回客戶端。
不僅是寫 Servet/JSP 需要理解 Web 容器,在 Java EE 的領域無論是哪個技術,都與容器息息相關,寫 Servlet/JSP 需要理解 Web 容器,寫 EJB 需要了解 EJB 容器,寫應用程式客戶端需要了解應用程式客戶端容器。
下圖是摘自 Java EE 8 Tutorial 中 Java EE Containers 文件的容器示意:
對於 Java EE 8 規範中 Servlet 4.0/JSP 2.3 等,你可以使用的實際容器可以是 Tomcat 9,或者是Glassfish 5,Tomcat 9 專注在 Web 容器的部份,Glassfish 5 是個完整的應用程式伺服器,當然也包括了 Web 容器的功能(當然,也還有其它廠商的實現)。