Tomcat8.5源码分析-ContextConfig

ContextConfig

还是先看看源码,看一下这个监听器做了什么。

public void lifecycleEvent(LifecycleEvent event) {

        // Identify the context we are associated with
        try {
            context = (Context) event.getLifecycle();
        } catch (ClassCastException e) {
            log.error(sm.getString("contextConfig.cce", event.getLifecycle()),
                    e);
            return;
        }

        // Process the event that has occurred
        if (event.getType().equals(Lifecycle.CONFIGURE_START_EVENT)) {
            configureStart();// 里面调用了webConfig()
        } else if (event.getType().equals(Lifecycle.BEFORE_START_EVENT)) {
            beforeStart();
        } else if (event.getType().equals(Lifecycle.AFTER_START_EVENT)) {
            // Restore docBase for management tools
            if (originalDocBase != null) {
                context.setDocBase(originalDocBase);
            }
        } else if (event.getType().equals(Lifecycle.CONFIGURE_STOP_EVENT)) {
            configureStop();
        } else if (event.getType().equals(Lifecycle.AFTER_INIT_EVENT)) {
            init();
        } else if (event.getType().equals(Lifecycle.AFTER_DESTROY_EVENT)) {
            destroy();
        }

    }

接着看configureStart():

protected synchronized void configureStart() {
        // Called from StandardContext.start()

        if (log.isDebugEnabled()) {
            log.debug(sm.getString("contextConfig.start"));
        }

        if (log.isDebugEnabled()) {
            log.debug(sm.getString("contextConfig.xmlSettings",
                    context.getName(),
                    Boolean.valueOf(context.getXmlValidation()),
                    Boolean.valueOf(context.getXmlNamespaceAware())));
        }

        webConfig();/* 这个方法解析了web.xml文件 */

        if (!context.getIgnoreAnnotations()) {
            applicationAnnotationsConfig();
        }
        if (ok) {
            validateSecurityRoles();
        }

        // Configure an authenticator if we need one
        if (ok) {
            authenticatorConfig();
        }

        // Dump the contents of this pipeline if requested
        if (log.isDebugEnabled()) {
            log.debug("Pipeline Configuration:");
            Pipeline pipeline = context.getPipeline();
            Valve valves[] = null;
            if (pipeline != null) {
                valves = pipeline.getValves();
            }
            if (valves != null) {
                for (int i = 0; i < valves.length; i++) {
                    log.debug("  " + valves[i].getClass().getName());
                }
            }
            log.debug("======================");
        }

        // Make our application available if no problems were encountered
        if (ok) {
            context.setConfigured(true);
        } else {
            log.error(sm.getString("contextConfig.unavailable"));
            context.setConfigured(false);
        }

    }

接着看webConfig:

    protected void webConfig() {
        /*
         * Anything and everything can override the global and host defaults.
         * This is implemented in two parts - Handle as a web fragment that gets
         * added after everything else so everything else takes priority - Mark
         * Servlets as overridable so SCI configuration can replace
         * configuration from the defaults
         */

        /*
         * The rules for annotation scanning are not as clear-cut as one might
         * think. Tomcat implements the following process: - As per SRV.1.6.2,
         * Tomcat will scan for annotations regardless of which Servlet spec
         * version is declared in web.xml. The EG has confirmed this is the
         * expected behaviour. - As per
         * http://java.net/jira/browse/SERVLET_SPEC-36, if the main web.xml is
         * marked as metadata-complete, JARs are still processed for SCIs. - If
         * metadata-complete=true and an absolute ordering is specified, JARs
         * excluded from the ordering are also excluded from the SCI processing.
         * - If an SCI has a @HandlesType annotation then all classes (except
         * those in JARs excluded from an absolute ordering) need to be scanned
         * to check if they match.
         */
        WebXmlParser webXmlParser = new WebXmlParser(
                context.getXmlNamespaceAware(), context.getXmlValidation(),
                context.getXmlBlockExternal());

        Set<WebXml> defaults = new HashSet<>();
        defaults.add(getDefaultWebXmlFragment(webXmlParser));

        WebXml webXml = createWebXml();

        // Parse context level web.xml
        // 解析context级的web.xml
        InputSource contextWebXml = getContextWebXmlSource();
        if (!webXmlParser.parseWebXml(contextWebXml, webXml, false)) {// 解析web.xml并创建对象
            ok = false;
        }

        ServletContext sContext = context.getServletContext();

        // Ordering is important here
        // 顺序在这里很重要
        // Step 1. Identify all the JARs packaged with the application and those
        // provided by the container. If any of the application JARs have a
        // web-fragment.xml it will be parsed at this point. web-fragment.xml
        // files are ignored for container provided JARs.
        // 第一步 .识别所有的JARs 包用那些container提供的应用。如果有任何应用JARs有web-fragment.xml将在此刻解析
        // 对于那些提供了JARs的container,web-fragment.xml被忽略。
        Map<String, WebXml> fragments = processJarsForWebFragments(webXml,
                webXmlParser);

        // Step 2. Order the fragments.
        // 第二步,给碎片进行排序
        Set<WebXml> orderedFragments = null;
        orderedFragments = WebXml
                .orderWebFragments(webXml, fragments, sContext);

        // Step 3. Look for ServletContainerInitializer implementations
        // 查找ServletContainerInitializer的实现
        if (ok) {
            processServletContainerInitializers();
        }

        if (!webXml.isMetadataComplete() || typeInitializerMap.size() > 0) {
            // Step 4. Process /WEB-INF/classes for annotations and
            // @HandlesTypes matches
            // 第四步.为注释传递 /WEB-INF.classes ,处理类型匹配
            Map<String, JavaClassCacheEntry> javaClassCache = new HashMap<>();

            if (ok) {
                WebResource[] webResources = context.getResources()
                        .listResources("/WEB-INF/classes");

                for (WebResource webResource : webResources) {
                    // Skip the META-INF directory from any JARs that have been
                    // expanded in to WEB-INF/classes (sometimes IDEs do this).
                    if ("META-INF".equals(webResource.getName())) {
                        continue;
                    }
                    processAnnotationsWebResource(webResource, webXml,
                            webXml.isMetadataComplete(), javaClassCache);
                }
            }

            // Step 5. Process JARs for annotations and
            // @HandlesTypes matches - only need to process those fragments we
            // are going to use (remember orderedFragments includes any
            // container fragments)
            // 第5步 为annotations 传递JARs
            if (ok) {
                processAnnotations(orderedFragments,
                        webXml.isMetadataComplete(), javaClassCache);
            }

            // Cache, if used, is no longer required so clear it
            javaClassCache.clear();
        }

        if (!webXml.isMetadataComplete()) {
            // Step 6. Merge web-fragment.xml files into the main web.xml
            // file.
            // 第六步.合并web-fragment.xml变成一个主要的web.xml
            if (ok) {
                ok = webXml.merge(orderedFragments);
            }

            // Step 7. Apply global defaults
            // Have to merge defaults before JSP conversion since defaults
            // provide JSP servlet definition.
            // 第七步.应用全局的缺省设置
            // 必须在JSP转换之前因为缺省的值提供了JSP servlet的定义
            webXml.merge(defaults);

            // Step 8. Convert explicitly mentioned jsps to servlets
            // 第八步.转换明确提及的jsps到servlets
            if (ok) {
                convertJsps(webXml);
            }

            // Step 9. Apply merged web.xml to Context
            // 第九步.应用碎片的web.xml到这个context
            if (ok) {
                configureContext(webXml);/* 创建了wrapper */
            }
        } else {
            webXml.merge(defaults);
            convertJsps(webXml);
            configureContext(webXml);
        }

        if (context.getLogEffectiveWebXml()) {
            log.info("web.xml:\n" + webXml.toXml());
        }

        // Always need to look for static resources
        // Step 10. Look for static resources packaged in JARs
        // 第十步 查找一些静态的资源包在JARs里面
        if (ok) {
            // Spec does not define an order.
            // Use ordered JARs followed by remaining JARs
            Set<WebXml> resourceJars = new LinkedHashSet<>();
            for (WebXml fragment : orderedFragments) {
                resourceJars.add(fragment);
            }
            for (WebXml fragment : fragments.values()) {
                if (!resourceJars.contains(fragment)) {
                    resourceJars.add(fragment);
                }
            }
            processResourceJARs(resourceJars);
            // See also StandardContext.resourcesStart() for
            // WEB-INF/classes/META-INF/resources configuration
        }

        // Step 11. Apply the ServletContainerInitializer config to the
        // context
        // 第十一步. 应用ServletContainerInitializer配置给这个context
        if (ok) {
            for (Map.Entry<ServletContainerInitializer, Set<Class<?>>> entry : initializerClassMap
                    .entrySet()) {
                if (entry.getValue().isEmpty()) {
                    context.addServletContainerInitializer(entry.getKey(), null);
                } else {
                    context.addServletContainerInitializer(entry.getKey(),
                            entry.getValue());
                }
            }
        }
    }

1.解析xml文件
2.创建wrapper,并调用addchild方法作为Context的子容器,
这样就可以loadonstartup时调用load方法。加载standardWrapper。
Tomcat8.5源码-StandardWrapper

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值