How Tomcat Works學習筆記

 

StandardContext

         Context代表一個web應用,每個Context包含多個代表servlet的Wrapper,同時Context還需要加載器和管理器。

StandardContext配置

         當StandardContext被構造以後,必須調用它的start方法,確保StandardContext爲HTTP請求提供服務。如果start失敗StandardContext的available屬性將會被設置爲false。

         爲了確保啓動方法運行成功,需要做適當的配置。在Tomcat部署過程中,配置StandardContext過程中需要做很多事情,首先,必須確保StandardContext能讀取%CATALINA_HOME%/conf目錄下所有應用部署都要使用的默認web.xml文件;其次,也必須確保StandardContext實例能夠處理應用級的web.xml,通常在其中有一些有效參數。

構造函數

         public StandardContext() {

        super();

        pipeline.setBasic(new StandardContextValve());

        namingResources.setContainer(this);

    }

         這裏最重要的步驟是爲管道pipeline添加StandardContextValue作爲基礎value,用來處理來自客戶端的HTTP請求。

啓動StandardContext

         start方法初始化StandardContext,並告知監聽則配置StandardContext實例,需要做如下事情:

1、  觸發BEFORE_START事件;

2、  設置available屬性值爲false;

3、  設置configured屬性值爲false;

4、  設置resources;

5、  設置加載器;

6、  設置管理器;

7、  初始化字符集匹配器;

8、  啓動其他分配給該Context的組件;

9、  啓動子容器Wrapper;

10、              啓動管道(pipeline);

11、              啓動管理器;

12、              觸發START事件,這裏監聽器(ContextConfig)會執行配置操作,配置成功以後會把configred爲true;

13、              檢測configred值,如果爲true,則做後面操作:調用postWelcomePages方法,加載需要在啓動時候加載的wrapper,設置available爲true;如果configred爲false,則調用stop方法;

14、              觸發AFTER_START事件。

start方法實現如下:

         public synchronized void start() throws LifecycleException {

        if (started)

            throw new LifecycleException

                (sm.getString("containerBase.alreadyStarted", logName()));

        if (debug >= 1)

            log("Starting");

        // Notify our interested LifecycleListeners

        lifecycle.fireLifecycleEvent(BEFORE_START_EVENT, null);

        if (debug >= 1)

            log("Processing start(), current available=" + getAvailable());

        setAvailable(false);

        setConfigured(false);

        boolean ok = true;

        // Add missing components as necessary

        if (getResources() == null) {   // (1) Required by Loader

            if (debug >= 1)

                log("Configuring default Resources");

            try {

                if ((docBase != null) && (docBase.endsWith(".war")))

                    setResources(new WARDirContext());

                else

                    setResources(new FileDirContext());

            } catch (IllegalArgumentException e) {

                log("Error initializing resources: " + e.getMessage());

                ok = false;

            }

        }

        if (ok && (resources instanceof ProxyDirContext)) {

            DirContext dirContext =

                ((ProxyDirContext) resources).getDirContext();

            if ((dirContext != null)

                && (dirContext instanceof BaseDirContext)) {

                ((BaseDirContext) dirContext).setDocBase(getBasePath());

                ((BaseDirContext) dirContext).allocate();

            }

        }

        if (getLoader() == null) {      // (2) Required by Manager

            if (getPrivileged()) {

                if (debug >= 1)

                    log("Configuring privileged default Loader");

                setLoader(new WebappLoader(this.getClass().getClassLoader()));

            } else {

                if (debug >= 1)

                    log("Configuring non-privileged default Loader");

                setLoader(new WebappLoader(getParentClassLoader()));

            }

        }

        if (getManager() == null) {     // (3) After prerequisites

            if (debug >= 1)

                log("Configuring default Manager");

            setManager(new StandardManager());

        }

        // Initialize character set mapper

        getCharsetMapper();

        // Post work directory

        postWorkDirectory();

        // Reading the "catalina.useNaming" environment variable

        String useNamingProperty = System.getProperty("catalina.useNaming");

        if ((useNamingProperty != null)

            && (useNamingProperty.equals("false"))) {

            useNaming = false;

        }

        if (ok && isUseNaming()) {

            if (namingContextListener == null) {

                namingContextListener = new NamingContextListener();

                namingContextListener.setDebug(getDebug());

                namingContextListener.setName(getNamingContextName());

                addLifecycleListener(namingContextListener);

            }

        }

        // Binding thread

        ClassLoader oldCCL = bindThread();

        // Standard container startup

        if (debug >= 1)

            log("Processing standard container startup");

        if (ok) {

            try {

                addDefaultMapper(this.mapperClass);

                started = true;

                // Start our subordinate components, if any

                if ((loader != null) && (loader instanceof Lifecycle))

                    ((Lifecycle) loader).start();

                if ((logger != null) && (logger instanceof Lifecycle))

                    ((Lifecycle) logger).start();

                // Unbinding thread

                unbindThread(oldCCL);

                // Binding thread

                oldCCL = bindThread();

                if ((cluster != null) && (cluster instanceof Lifecycle))

                    ((Lifecycle) cluster).start();

                if ((realm != null) && (realm instanceof Lifecycle))

                    ((Lifecycle) realm).start();

                if ((resources != null) && (resources instanceof Lifecycle))

                    ((Lifecycle) resources).start();

                // Start our Mappers, if any

                Mapper mappers[] = findMappers();

                for (int i = 0; i < mappers.length; i++) {

                    if (mappers[i] instanceof Lifecycle)

                        ((Lifecycle) mappers[i]).start();

                }

                // Start our child containers, if any

                Container children[] = findChildren();

                for (int i = 0; i < children.length; i++) {

                    if (children[i] instanceof Lifecycle)

                        ((Lifecycle) children[i]).start();

                }

                // Start the Valves in our pipeline (including the basic),

                // if any

                if (pipeline instanceof Lifecycle)

                    ((Lifecycle) pipeline).start();

                // Notify our interested LifecycleListeners

                lifecycle.fireLifecycleEvent(START_EVENT, null);

                if ((manager != null) && (manager instanceof Lifecycle))

                    ((Lifecycle) manager).start();

            } finally {

                // Unbinding thread

                unbindThread(oldCCL);

            }

        }

        if (!getConfigured())

            ok = false;

        // We put the resources into the servlet context

        if (ok)

            getServletContext().setAttribute

                (Globals.RESOURCES_ATTR, getResources());

        // Binding thread

        oldCCL = bindThread();

        // Create context attributes that will be required

        if (ok) {

            if (debug >= 1)

                log("Posting standard context attributes");

            postWelcomeFiles();

        }

        // Configure and call application event listeners and filters

        if (ok) {

            if (!listenerStart())

                ok = false;

        }

        if (ok) {

            if (!filterStart())

                ok = false;

        }

        // Load and initialize all "load on startup" servlets

        if (ok)

            loadOnStartup(findChildren());

        // Unbinding thread

        unbindThread(oldCCL);

        // Set available status depending upon startup success

        if (ok) {

            if (debug >= 1)

                log("Starting completed");

            setAvailable(true);

        } else {

            log(sm.getString("standardContext.startFailed"));

            try {

                stop();

            } catch (Throwable t) {

                log(sm.getString("standardContext.startCleanup"), t);

            }

            setAvailable(false);

        }

        // Notify our interested LifecycleListeners

        lifecycle.fireLifecycleEvent(AFTER_START_EVENT, null);

}

invoke方法

         在Tomcat4中invoke方法被連接器調用,如果StandardContext是Host的子容器則被Host的invoke方法調用,在invoke方法中會檢測是否重載應用,會等待應用重載完成,方法實現如下:

         public void invoke(Request request, Response response)

        throws IOException, ServletException {

        // Wait if we are reloading

        while (getPaused()) {

            try {

                Thread.sleep(1000);

            } catch (InterruptedException e) {

                ;

            }

        }

        // Normal request processing

        if (swallowOutput) {

            try {

                SystemLogHandler.startCapture();

                super.invoke(request, response);

            } finally {

                String log = SystemLogHandler.stopCapture();

                if (log != null && log.length() > 0) {

                    log(log);

                }

            }

        } else {

            super.invoke(request, response);

        }

}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章