我們知道 Java Web 應用是基于 Servlet 規範運轉的,那麼 Servlet 本身又是如何運轉的呢?為何要設計成這樣呢
Servlet 頂層類關聯圖
從上圖可以看出 Servlet 規範就是基于這幾個類運轉的,與 Servlet 主動關聯三個類 ServletConfig、ServletRequest , ServletResponse
這三個類都是通過容器傳遞給 Servlet 的
- ServletConfig 在 Servlet 初始化時傳給 Servlet
- 後兩個在請求達到時調用 Servlet 時才傳遞
我們很清楚ServletRequest 和 ServletResponse 在 Servlet 運作時的意義,但是 ServletConfig 和 ServletContext 對 Servlet 有何價值?
- 仔細檢視 ServletConfig 接口中聲明的方法,發現都是為了擷取這個 Servlet 的一些配置屬性,而這些配置屬性可能在 Servlet 運作時被用到。
-
ServletContext 又是幹什麼的呢? Servlet 的運作模式是一個典型的“握手型的互動式”運作模式。
所謂“握手型的互動式”就是兩個子產品為了交換資料通常都會準備一個交易場景,這個場景一直跟随交易過程直到交易完成。這個交易場景的初始化是根據這次交易對象指定的參數來定制的,這些指定參數通常就會是一個配置類。是以對号入座,
- 交易場景由 ServletContext 描述
- 定制的參數集合由 ServletConfig描述
- ServletRequest 和 ServletResponse 是要互動的具體對象,它們通常都是作為運輸工具來傳遞互動結果
ServletConfig 是在 Servlet init 時由容器傳過來的,那麼 ServletConfig 到底是個什麼對象呢?
ServletConfig,ServletContext在 Tomcat 容器中的類關系
可以看出 StandardWrapper 和 StandardWrapperFacade 都實作了 ServletConfig 接口,而 StandardWrapperFacade 是 StandardWrapper 門面類。
是以傳給 Servlet 的是 StandardWrapperFacade 對象,它能夠保證從 StandardWrapper 中拿到 ServletConfig 所規定的資料,而又不把 ServletConfig不關心的資料暴露給 Servlet
ServletContext 與 ServletConfig 也有類似的結構,Servlet 中能拿到的 ServletContext 的實際對象是 ApplicationContextFacade ApplicationContextFacade 同樣保證 ServletContex隻能從容器中拿到它該拿的資料,它們都起到對資料的封裝作用,它們使用的都是門面設計模式
通過 ServletContext 可以拿到 Context 容器中一些必要資訊,比如應用的工作路徑,容器支援的 Servlet 最小版本等。
Servlet 中定義的兩個 ServletRequest 和 ServletResponse 它們實際的對象又是什麼呢?
我們在建立自己的 Servlet 類時通常使用的都是 HttpServletRequest 和 HttpServletResponse,它們繼承了 ServletRequest 和** ServletResponse**
為何 Context 容器傳過來的 ServletRequest、ServletResponse 可以被轉化為 HttpServletRequest 和 HttpServletResponse 呢?
Tomcat 接受到請求首先将會建立 org.apache.coyote.Request 和org.apache.coyote.Response
這兩個類是 Tomcat 内部使用的描述一次請求和響應的資訊類
它們是一種輕量級的類,作用就是在伺服器接收到請求後,經過簡單解析将這個請求快速配置設定給後續線程去處理,是以它們的對象很小,很容易被 JVM 回收。
接下來當交給一個使用者線程去處理這個請求時又建立 org.apache.catalina.connector.Request 和 org.apache.catalina.connector.Response .這兩個對象一直穿越整個 Servlet 容器直到要傳給 Servlet,傳給 Servlet 的是 Request 和 Response 的門面類 RequestFacade 和 ResponseFacade,這裡使用門面模式與前面一樣都是基于同樣的目的即封裝容器中的資料
與Request 相關的類結構圖
一次請求對應的 Request 和 Response 的類轉化如下圖
Request 和 Response 的轉變過程