淺析Tomcat中Servlet的執行原理
最近幾天在學習Servlet,由於個人學習能力有限,學的稀裡糊塗的,於是今天花了將近八個小時的時間,才把Servlet的執行原理稍微弄懂了那麼一點點,我把它分享出來,希望對你也有一些幫助。
![](http://mmbiz.qpic.cn/mmbiz/DyxI4HFFkdvicCia2pQicfwE94RJqFkDsoeprkd33a6bAudbYKTIc82icr1kGdsb567ru8FtJfPlsMw7M0aCGhFvcA/640.jpeg)
當我們使用搜索引擎搜尋內容時,第一步要做的就是輸入搜尋關鍵詞,然後伺服器根據關鍵詞返回給我們想要的內容,當我們輸入不同的關鍵詞時,伺服器返回的內容也會有所不同,而伺服器向瀏覽器返回的不同內容也就是我們所說的動態的Web資源。如果想要開發這樣的功能,就必須用到Servlet技術(此文章僅針對Java Web領域,至於其他的程式語言所使用的技術,因為個人能力有限,暫時還不知道)。講到這裡,可能大家還不是很清楚Servlet究竟是什麼東西?其實Servlet是sun公司提供的一門用於開發動態web資源的技術。Sun公司在其API中提供了一個servlet介面,使用者若想開發一個動態web資源(即開發一個Java程式向瀏覽器輸出資料),需要完成以下2個步驟:
1、編寫一個Java類,實現servlet介面。
2、把開發好的Java類部署到web伺服器中。
上面對Servlet的理解相對狹義,廣義的對Servlet的理解是指任何實現了這個Servlet介面的類,而一般情況下,我們都將Servlet理解為後者。
![](http://mmbiz.qpic.cn/mmbiz/DyxI4HFFkdvicCia2pQicfwE94RJqFkDsoeprkd33a6bAudbYKTIc82icr1kGdsb567ru8FtJfPlsMw7M0aCGhFvcA/640.jpeg)
Servlet執行全過程
寫在前面:Servlet的生命週期包含例項化、初始化、服務和銷燬四個階段。
1、例項化Servlet
當瀏覽器向伺服器傳送一個請求之後,伺服器首先做的是先檢查是否已經裝載並建立了該Servlet的例項物件,如果已經建立,則直接執行第四步,否則執行第二步。補充一點:如果我們在配置檔案中為該Servlet類設定load-on-startup的屬性值為1,那麼伺服器在啟動之時便會直接建立該Servlet例項並初始化。
2、初始化Servlet
當我們在初始化Servlet之前,伺服器會建立一個ServletConfig物件,同時將Servlet配置檔案當前Servlet中的一些初始化引數封裝進ServletConfig物件,然後會呼叫Servlet的init(ServletConfig config)初始化Servlet物件。
3、服務階段
Tomcat 一接受到瀏覽器的請求首先將會建立 org.apache.coyote.Request 和 org.apache.coyote.Response,這兩個類是 Tomcat 內部使用的描述一次請求和相應的資訊類它們是一個輕量級的類,它們作用就是在伺服器接收到請求後,經過簡單解析將這個請求快速的分配給後續執行緒去處理,所以它們的物件很小,很容易被 JVM 回收。
接下來這兩個物件會交給Tomcat的聯結器Connector,Connector會建立一個Request和Response物件,用於和前端Client交換資料,然後產生一個執行緒,並將Request物件和Response物件傳遞給執行緒,注意此時的兩個物件的型別分別是org.apache.catalina.connector. Request 和 org.apache.catalina.connector. Response。你以為到這裡就完了嗎?並不會tomcat會繼續將其封裝成RequestFacade和ResponseFacade,這裡的封裝使用了名為外觀模式的設計模式,至於為什麼這麼做,因為我還沒有了解過設計模式,所以就不多說了,但大體是為了遮蔽掉原本類的一些方法,避免干擾。
至此,請求的轉換結束,tomcat會把這兩個引數傳遞給servlet的service方法。那麼問題又來了,我們檢視servlet類的父類HttpServlet時,會發現它有兩個service方法,一個是 public void service(ServletRequest req, ServletResponse res),一個是protected void service(HttpServletRequest req, HttpServletResponse resp),此時omcat呼叫的是哪個方法呢?答案是修飾符為public的service方法,因為只有這個方法才會被Tomcat自動呼叫,下面是該public void service方法的原始碼。
通過原始碼我們可以發現,在public的service方法中會將request和response強轉,然後呼叫protected的service方法,所以我們在servlet中重寫protected的service方法時完全可以的。
下面我們再看看protected的service方法的原始碼:
在這個方法中,service方法會根據的瀏覽器請求的型別再去呼叫相應的doXXX方法,比如doGet、doPost等。
4、銷燬Servlet
當我們關閉伺服器時,相應的Servlet例項就會執行destory方法進行銷燬。
最後附上一張今天整理的和servlet相關的類以及它們之間的一些關係。