Tomcat中容器是什么以及容器與容器之間的數量關系。


Tomcat容器到底是什么

學java有一小段時間了,一直使用Tomcat,也知道Tomcat是一個大的Servlet容器,里面還有許多子容器,容器之間都是相互嵌套的。也看過一下接收Tomcat的文章,都是一幅圖,圖中有好多個框框相互嵌套,表示容器與容器之間的相互嵌套,也沒什么說明,把我看得雲里霧里的。所以要想了解的更多必須自己探索一下。

  現在把自己學到的一點點知識記下來,以免忘記了。

  都說Tomcat是一個容器,那么這個容器到底是什么東西,因為說它是一個容器我還是覺得有點抽象,而我看了很多文章都沒看到有人說。所以,我想知道Tomcat的本質。腦袋有點轉不過彎來,寫到這里才發現既然Tomcat是用java寫的那它的容器的本質應該就是java類啦。

  在開始探索之前我就知道Tomcat中有Server、Service、Engine、Host.....等容器。這些容器與容器之間相互嵌套。既然這些容器的本質就是實實在在的java類(容器就是java類,已經夠具體了,這樣我才能理解,因為我天天寫java類 ^v^ ),那這些不同的容器分別使用什么樣的java類來描述的呢???我點是我想要知道的。

  經過一番探索,知道這些容器都是有生命周期的java類,他們都繼承了共同的接口 Lifecycle 。所以Lifecycle就是這些容器這些java類的頂層接口了。下面是我畫的繼承體系圖。

圖一:圖片保存下來看吧,博客園的圖片編輯無語,改天好好研究一下怎么讓他彈出來再改。

 通過圖中的類名就可以知道哪些類是表示Server,哪些是表示Service哪些是。。。。。。

Tomcat中的這些容器都是有生命周期的容器,那么它的類肯定就有聲明周期方法了。先看看頂層接口 Lifecycle ,這個接口里面主要定義了一些生命周期的方法。所以,繼承自這個接口的所有容器都有生命周期。

圖二:

 init()方法:初始化容器組件,它必須在啟動容器之前調用。它會創建許多對象。

start():啟動容器,比如啟動一個Server。

stop():停止執行

destroy():銷毀這個容器。

Server容器:一個StandardServer類實例就表示一個Server容器

Service容器:一個StandardService類實例就表示一個Service容器

Engine容器:一個StandardEngine類實例就表示一個Engine容器。

Host容器:一個StandardHost類實例就表示一個Host容器。

Context容器:一個StandardContext類實例就表示一個Context容器。

Wrapper容器:一個StandardWrapper類實例就表示一個Wrapper容器。

以上一共有六種類型的容器,從上到下嵌套,也就是Server容器里面有Service容器,Service容器里面有Engine容器。。。。。。這就是這些容器之間的嵌套關系。

需要注意的是,這些容器之間存在父子關系,但是他們對應的java類之間卻不是父子關系。由圖一可以看出來。

父容器與子容器之間的數量關系

這些父容器和子容器之間有什么樣的數量關系呢???

一個Server容器可以有多個Service容器

   /**
     * The set of Services associated with this Server.用一個數組來保存子容器的引用 */
    private Service services[] = new Service[0];

一個Service容器只可以有一個子容器。

/**
     * The Container associated with this Service. (In the case of the
     * org.apache.catalina.startup.Embedded subclass, this holds the most
     * recently added Engine.)
    它不是用一個數組來保存子容器的引用的。所以直接的子容器只有一個。
*/ protected Container container = null;

這里用Container來表示子容器,根據圖一可以看出,Container是Engine、Host、Context、Wrapper 接口的父接口,所以Service容器下面的子容器可能是Engine、Host、Context、Wrapper。但是我覺得一般情況下Service的子容器都是Engine容器吧。
一個Engine容器里面可以有多個 Host 容器

    /**
     * Add a child Container, only if the proposed child is an implementation
     * of Host.
     *
     * @param child Child container to be added
     */
    @Override
    public void addChild(Container child) {

        if (!(child instanceof Host))//這里說明Engine的子容器只能是Host throw new IllegalArgumentException
                (sm.getString("standardEngine.notHost"));
        super.addChild(child);

    }

一個Host容器里可以有多個 Context 容器。

    /**
     * Add a child Container, only if the proposed child is an implementation
     * of Context.
     *
     * @param child Child container to be added
     */
    @Override
    public void addChild(Container child) {

        child.addLifecycleListener(new MemoryLeakTrackingListener());

        if (!(child instanceof Context))//這里說明Host容器的子容器只能是Context容器 throw new IllegalArgumentException
                (sm.getString("standardHost.notContext"));
        super.addChild(child);

    }

一個Host容器中可以有多個Wrapper容器。

    /**
     * Add a child Container, only if the proposed child is an implementation
     * of Wrapper.
     *
     * @param child Child container to be added
     *
     * @exception IllegalArgumentException if the proposed container is
     *  not an implementation of Wrapper
     */
    @Override
    public void addChild(Container child) {

        // Global JspServlet
        Wrapper oldJspServlet = null;

        if (!(child instanceof Wrapper)) {//這里說明Context容器的子容器只能是Wrapper容器。 throw new IllegalArgumentException
                (sm.getString("standardContext.notWrapper"));
        }
      //這里刪除了部分代碼 
    }

Wrapper容器下面不允許再有子容器。Wrapper容器是最底層的容器。如果添加子容器的話會拋出異常。

    /**
     * Refuse to add a child Container, because Wrappers are the lowest level
     * of the Container hierarchy.
     *
     * @param child Child container to be added
     */
    @Override
    public void addChild(Container child) {

        throw new IllegalStateException
            (sm.getString("standardWrapper.notChild"));

    }

服務器接收到請求信息后如何傳到我們編寫的HttpServlet的呢??如果是SpringMVC的話會先到DispatcherServlet再到Controller,而DispatcherServlet也是HttpServlet的一個間接子類。在下一篇文章Tomcat是如何將請求一步步傳遞到我們編寫的HttpServlet類中的

 


免責聲明!

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



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