tomcat系列之二:Servlet規范


一,當Http服務器接收請求后,如何知道調用哪些java類來處理請求呢?

  有些類可能就是用來封裝變量的,有些類才是用來處理請求的。為了識別出那些具有處理請求的類,定義了一個接口,這個接口就叫Servlet接口,如果想要讓業務類具備處理請求的能力,都必須實現這個接口,實現了接口的業務類叫做Servlet。

二,對於特定的請求,Http服務器如何知道由哪個Servlet來處理?Servlet又是由誰來實例化呢

1,於是又有了Servlet容器。Http服務器把請求交給Servlet容器去處理,Servlet容器會將請求轉發到具體的Servlet,如果這個Servlet還沒創建,就加載並實例化這個Servlet,然后調用這個Servlet的接口方法。

Servlet接口其實是Servlet容器和具體業務類之間的接口:

Http服務器不直接調用業務類,而是把請求交給容器來處理,容器通過Servlet接口調用業務類。因此Servlet接口和Servlet容器的出現,使Http服務器和業務類解耦。

Servlet規范:Servlet接口 + Servlet容器。Tomcat按照Servlet規范的要求實現了Servlet容器,同時它也具有Http服務器的功能。(如果我們要實現新的業務功能,只需要實現一個        Servlet,然后把它注冊到Tomcat(Servlet容器)中,剩下的事情由Tomcat幫我們來處理)。

三,Servlet接口

1,Servlet接口定義了五個方法:

public interface Servlet {
    void init(ServletConfig config) throws ServletException;
    
    ServletConfig getServletConfig();
    
    void service(ServletRequest req, ServletResponse res)throws ServletException, IOException;
    
    String getServletInfo();
    
    void destroy();
}

 1.1,init(ServletConfig config):

  和生命周期有關的方法,Servlet容器在加載Servlet類的時候會調用init方法。可能會在init方法里初始化一些資源。比如Springmvc中的DispatcherServlet,在init方法中創建了自己的spring容器。

1.2,ServletConfig getServletConfig()

·  ServletConfig就是封裝Servlet的初始化參數。可以在web.xml給Servlet配置參數,然后在程序中通過getServletConfig方法拿到這些參數。

1.3,service(ServletRequest req, ServletResponse res)

  業務類在這個方法里實現處理邏輯。ServletRequest用來封裝請求信息,ServletResponse用來封裝響應信息。本質上這兩個類是對通信協議的封裝。

Http協議中的請求和響應就是對應了HttpServletRequest和HttpServletResponse這兩個類。我們可以通過HttpServletRequest來獲取所有請求相關的信息,包括請求路徑,Cookie,Http頭,請求參數等。

1.4,String getServletInfo()

1.5,destroy()

  和生命周期有關的方法,Servlet容器在卸載Servlet類的時候會調用destory方法。在destory方法里釋放這些資源。

四,Servlet容器

1,Servlet容器工作流程

當客戶請求某一個資源時,Http服務器會用一個ServletRequest對象把客戶的請求信息封裝起來,然后調用Servlet容器的service方法,Servlet容器拿到請求后,根據請求的URL和Servlet的映射關系,找到相應的Servlet,如果Servlet還沒有被加載,就用反射機制創建這個Servlet,並調用Servlet的init方法來完成初始化,接着調用Servlet的service方法來處理請求,把ServletResponse對象返回給Http服務器,Http服務器會把響應發送給客戶端。

2,Web應用

2.1,Servlet容器負責實例化和調用Servlet,那么Servlet是怎么注冊到Servlet容器的呢?

  我們一般以Web應用程序的方式來部署Servlet的。根據Servlet規范,Web應用程序有一定的目錄結構:

| -  MyWebApp
      | -  WEB-INF/web.xml        -- 配置文件,用來配置 Servlet 等
      | -  WEB-INF/lib/           -- 存放 Web 應用所需各種 JAR 包
      | -  WEB-INF/classes/       -- 存放你的應用類,比如 Servlet 類
      | -  META-INF/              -- 目錄存放工程的一些信息

在這個目錄下分別放置了Servlet的類文件,配置文件,靜態資源文件,Servlet容器通過讀取配置文件,就可以找到並加載Servlet。

2.2,Servlet規范中定義了ServletContext這個接口來對應一個Web應用。

  Web應用部署好以后,Servlet容器在啟動時會加載Web應用,並為每個Web應用創建唯一的ServletContext對象。你可以把ServletContext看成是一個全局對象,一個Web應用可能有多個Servlet,這些Servlet可以通過全局的ServletContext來共享數據,這些數據包括Web應用的初始化參數,Web應用目錄下的文件資源等。因為ServletContext持有所有Servlet實例,還可以通過它來實現Servlet請求的轉發。

2.3,擴展機制:Filter和Listener

Filter:過濾器,這個接口允許對請求和響應做一些統一的定制化處理,比如可以根據請求的頻率來限制訪問,根據國家地區的不同來修改響應的內容。

  過濾器原理:Web應用部署完以后,Servlet容器需要實例化Filter並把Filter鏈接成一個FilterChain。當請求進來時,獲取第一個Filter並調用doFilter方法,doFilter方法負責調用 FilterChain的下一個Filter。

 

Listener:監聽器,當Web應用在Servlet容器中運行時,Servlet容器內部會不斷發生各種事件,比如Web應用的啟動和停止,用戶請求到達等。Servlet容器提供了一些默認的監聽器來監聽這些事件,當事件發生時,Servlet容器會負責調用監聽器的方法。自定義監聽器需要把監聽器配置在web.xml中。比如:Spring就實現了自己的監聽器,用來監聽ServletContext的啟動事件,目的是當Servlet容器啟動時,創建並初始化全局的Spring容器。

 

五,各種容器(Web容器,Servlet容器,Spring容器,SpringMvc容器)

1,Tomcat在啟動時給每個Web應用創建一個全局的上下文環境,這個上下文就是ServletContext,為后面的Spring容器提供宿主環境。

2,Tomcat在啟動過程中觸發容器初始化事件,Spring的ContextLoaderListener會監聽到這個事件,它的contextInitialized方法會被調用,然后Spring會初始化全局的Spring根容器,這個就是Spring的Ioc容器,Ioc容器初始化完畢后,Spring將其存儲到ServletContext中,便於以后獲取。

3,Tomcat啟動時還會掃描Servlet,一個Web應用中的Servlet可以有多個,以SpringMvc中的DispatcherServet為例,這個Servlet實際上是一個標准的前端控制器,用來轉發,匹配,處理每個Servlet請求。

4,Servlet一般會延遲加載,當第一個請求到達時,Tomcat發現DispatcherServet還沒有被實例化,就調用DispatcherServet的init方法,DispatcherServet在初始化的時候會建立自己的容器,叫做SpringMvc容器,用來持有SpringMvc相關的Bean。同時,SpringMvc還會通過ServletContext拿到Spring根容器,並把Spring根容器設置為SpringMvc容器的父容器,Spring容器可以訪問父容器中的Bean,但是父容器不能訪問子容器中的Bean(Spring容器不能訪問SpringMvc容器里的Bean --->Controller里可以訪問Service對象,但是在Service里不可以訪問Controller對象)。

 

 

 web容器中有servlet容器,spring項目部署后存在spring容器和springmvc容器。其中spring控制service層和dao層的bean對象。springmvc容器控制controller層bean對象。servlet容器控制servlet對象。項目啟動是,首先 servlet初始化,初始化過程中通過web.xml中spring的配置加載spring配置,初始化spring容器和springmvc容器。待容器加載完成。servlet初始化完成,則完成啟動。
HTTP請求到達web容器后,會到達Servlet容器,容器通過分發器分發到具體的spring的Controller層。執行業務操作后返回結果。
---------------------

參考連接:https://blog.csdn.net/zhanglf02/article/details/89791797

Spring MVC 中的 DispatcherServl...

極客時間版權所有: https://time.geekbang.or


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM