Tomcat架構解析(三)-----Engine、host、context解析以及web應用加載


  上一篇博文介紹了Server的創建,在Server創建完之后,就進入到Engine的創建過程,如下:

  一、Engine的創建

  1、創建Engine實例

  

  當前次棧頂元素為Service對象,通過Service對象的setContainer()方法,將Engine對象添加到Service中。

  2、為Engine添加集群配置

  

  3、為Engine添加生命周期監聽器

  

  4、為Engine添加安全配置

  

  

  

  二、Host的創建

  1、創建Host的實例

  

  addCallMethod(String rule,String methodName,int paraNumber):該方法同樣設置對象的屬性,但更加靈活,不需要對象具有setter。根據rule規則指定的屬性,調用對象的methodName方法,paraNumber參數是表示方法需要的參數個數。

  當paraNumber=0時,可以單獨使用,不然需要配合addCallParam方法。

  2、為Host添加集群

  

  3、為Host添加生命周期管理

  

  4、為Host添加安全配置

  

  

 

  三、Context的解析

  Context就對應着具體的web應用,說白了,就是平時開發的各種項目。但是Catalina中的Context配置並不只是在一處配置,一般配置Context有如下幾種方式:

  a、在Tomcat的server.xml中進行配置Context的相關信息(一般不這么干,因為煩);

  b、將應用丟到部署目錄(也就是/webapps下),這種比較常見。原理就是Tomcat通過HostConfig對象自動掃描部署目錄,以context.xml為基礎進行解析創建;

  c、在Eclipse或IDEA等開發工具中將web應用部署在Tomcat中,此時Context的相應配置會動態自動的更新到server.xml文件中(開發過程中肯定是這么干了)。

  1、Context實例化

  

  

  后續就是為Context添加生命周期監聽器、類加載器、會話管理器、初始化參數、安全配置以及cookie處理器等等。。。

 

  四、web應用加載

 當整個server開始啟動的時候,肯定要將部署的所有的web應用都加載進來,web應用在Tomcat中的默認實現類為StandardContext,主要過程如下:

 

   1、StandardHost

   加載web應用的入口主要有兩個:

   a、根據前面的博文可以知道,在Host解析的過程中,如果存在Context子元素,則會解析Context,並將Context添加到Host對象中,作為Host的子容器。當Host啟動時(調用start()),由生命周期

  管理接口的start()方法默認啟動子容器的start()方法;

  

  其中docBase代表web應用所在地址,path則是web應用的訪問地址。前面也說到了,這種方式比較煩。。。

  b、HostConfig自動掃描部署目錄,掃描到web應用之后,創建相關Context實例。

  下面來具體解釋下StandardHost的啟動加載過程:

  

  a、添加ErrorReportValve

  在服務器處理異常時輸出錯誤頁面。當然如果在web.xml中配置了錯誤頁面,則這個是不起作用的,只有web.xml中沒有配置錯誤頁面,該配置才有效。當然web.xml中配置錯誤頁面的粒度是針對整個web應用,后者則是針對整個Host,粒度較大。

  b、調用StandardHost的父類ContainerBase的startInternal()

  該方法啟動虛擬機,具體包括:

    ------如果配置了集群cluster,則啟動;

    |-----如果配置了安全組件realm,則啟動;

    |-----啟動子容器,當Host中包含子節點時,例如Context;

    |-----啟動Host持有的pipeline組件;

    |-----設置Host的狀態為starting,觸發start_event生命周期事件。HostConfig監聽該事件,掃描部署目錄,自動創建StandardContext實例,然后啟動這些Context實例;

    ------啟動Host層級的后台任務處理,cluster后台任務處理(檢測心跳等等)、realm后台任務處理、pipeline后台任務處理。

 

  2、HostConfig

  HostConfig主要作用是自動掃描Tomcat部署目錄,創建StandardContext。HostConfig實現了LifecycleListener接口,主要包括start_event、periodic_event、stop_event三個生命周期事件。

  a、start_event事件

  Host啟動時觸發,但是要求Host的deplyOnStartUp屬性為true,當服務器啟動時,部署所有的web應用。該事件處理包括三個步驟:

  ------Context描述文件部署

  |-----web目錄部署

  ------war包部署

  b、periodic_event事件

  Catalina容器支持定期執行自身以及其子容器的后台處理過程,此種機制能夠定時掃描到web應用的變更,並重新加載,后台任務處理完成后,觸發periodic_event事件。HostConfig接收到此事件后,若web應用有改動,則重新加載。

 

  五、MapperListener和Mapper

  1、MapperListener的初始化

  作用:實現了ContainerListener與 LifecycleListener接口,監聽tomcat組件的變化,當有Host,Context及Wrapper變更時,調用Mapper相關方法,增加或者刪除Host,Context,Wrapper等。

/**
     * Initialize associated mapper.
     */
    public void init() {

        // Find any components that have already been initialized since the
        // MBean listener won't be notified as those components will have
        // already registered their MBeans jiaan
        findDefaultHost();
        
        Engine engine = (Engine) connector.getService().getContainer();
        engine.addContainerListener(this);
        
        Container[] conHosts = engine.findChildren();
        for (Container conHost : conHosts) {
            Host host = (Host) conHost;
            if (!LifecycleState.NEW.equals(host.getState())) {
                host.addLifecycleListener(this);
                // Registering the host will register the context and wrappers
                registerHost(host);
            }
        }
    }

  Connector是由Service負責管理,然后給所有的子容器都添加生命周期監聽器。然后將Host及其子容器Context,Context的子容器Wrapper注冊到MapperListener的Mapper對象。

 

 2、Mapper

  Mapper中維護着一個Host數組,每個Host中有一個ContextList,這個ContextList中維護着一個Context數組。每個Context維護着一個defaultWrapper,三個Wrapper數組(exactWrappers、wildcardWrappers、extensionWrappers)。

  下面對Host、Context及Wrapper進行功能上的介紹:

  Host:代表一個虛擬主機,各Host的name不能相同,appBase代表各虛擬主機的應用發布位置;
  Context:代表一個應用,Context可以根據應用的/WEB-INF/web.xml文件中定義的servlet來處理請求。一個Host下可以有多個Context; 
  Wrapper: 代表一個Servlet或者jsp,它負責管理一個 Servlet,包括的 Servlet 的裝載、初始化、執行以及資源回收。

 

  通過MapperListener以及Mapper,當客戶端發出請求時,就可以根據url找到對應的Wrapper(就是Servlet),解釋如下:

  

  •   1、用戶在瀏覽器中輸入網址localhost:8080/test/index.jsp,請求被發送到本機端口8080,被在那里監聽的Coyote HTTP/1.1 Connector獲得;
  •   2、Connector把該請求交給它所在的Service的Engine(Container)來處理,並等待Engine的回應;
  •   3、Engine獲得請求localhost/test/index.jsp,匹配所有的虛擬主機Host;
  •   4、Engine匹配到名為localhost的Host(即使匹配不到也把請求交給該Host處理,因為該Host被定義為該Engine的默認主機),名為localhost的Host獲得請求/test/index.jsp,匹配它所擁有的所有Context。Host匹配到路徑為/test的Context(如果匹配不到就把該請求交給路徑名為“ ”的Context去處理);
  •   5、path=“/test”的Context獲得請求/index.jsp,在它的mapping table中尋找出對應的Servlet(這地方就是用到了上面的Mapper去找到對應的Servlet對象)。Context匹配到URL Pattern為*、jsp的Servlet,對應於JspServlet類;
  •   6、構造HttpServletRequest對象和HttpServletResponse對象,作為參數調用JspServlet的doGet()或doPost(),執行業務邏輯、數據存儲等;
  •   7、Context把執行完之后的HttpServletResponse對象返回給Host;
  •   8、Host把HttpServletResponse對象返回給Engine;
  •   9、Engine把HttpServletResponse對象返回Connector;
  •   10、Connector把HttpServletResponse對象返回給客戶Browser。

  

  大概介紹了Tomcat中的Engine、Host、Context的解析,並且簡單介紹了拿到客戶端請求如何找到對應的Servlet。下篇博文主要介紹Tomcat如何與客戶端建立連接,待續~~~

 


免責聲明!

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



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