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);

        }

}

 

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