热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【Tomcat】源码分析ContextConfig,web.xml的解析

文章目录1.ContextConfig的基本流程2.ContextConfig的核心功能2.1web-fragment.xml知识2.2ServletContainerInitia

文章目录

    • 1. ContextConfig的基本流程
    • 2. ContextConfig的核心功能
      • 2.1 web-fragment.xml知识
      • 2.2 ServletContainerInitializers的实现类
      • 2.3 web.xml文件加载的细节


1. ContextConfig的基本流程

同HostConfig一样,ContextConfig也是在初始化阶段由Digester解析server.xml的时候添加到StandardContext上的监听器,在后续的启动阶段,会触发调用这个之前创建的监听器:
在这里插入图片描述
初始化期间完成注册流程:

load() //catalina
->Digester digester = createStartDigester(); //catalina.load()
->digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/")); //catalina.createStartDigester()
->ruleSet.addRuleInstances(this); //Digester. addRuleSet()
-> digester.addRule(prefix + "Context",new LifecycleListenerRule("org.apache.catalina.startup.ContextConfig","configClass")); //ContextRuleSet.addRuleInstances()
->完成注册

ContextConfig 实现了LifecycleListener,就是一个监听器的实例:

public class ContextConfig implements LifecycleListener{public void lifecycleEvent(LifecycleEvent event){....do many things here!}}

//定义前缀"Server/Service/Engine/Host/",后面会拼接这个前缀,作为容器对象的路径的前缀
digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/"));

//拼接表示容器的全路径信息
//Server/Service/Engine/Host/Context表示context需要添加一个ContextConfig 监听器
//最终加到context实现类StandardContext的集合属性lifecycleListeners中(该属性继承自父接口)
digester.addRule(prefix + "Context",new LifecycleListenerRule("org.apache.catalina.startup.ContextConfig","configClass"));

触发解析的流程,位于启动流程内:

startInternal() //StandardContext
->fireLifecycleEvent(Lifecycle.CONFIGURE_START_EVENT, null); //StandardContext.startInternal()
-> for (LifecycleListener listener : lifecycleListeners) {listener.lifecycleEvent(event);//递归} //LifecycleBase .fireLifecycleEvent()
->ContextConfig实例的fireLifecycleEvent()
-> if (event.getType().equals(Lifecycle.CONFIGURE_START_EVENT)) {configureStart(); //消息类型为CONFIGURE_START_EVENT时} //ContextConfig.fireLifecycleEvent()

调用 listener.lifecycleEvent(event);时,注意event=start
参见入参的源头代码: fireLifecycleEvent(Lifecycle.CONFIGURE_START_EVENT, null);


2. ContextConfig的核心功能

ContextConfig主要是处理web应用的配置文件:

org.apache.catalina.startup.ContextConfig {//监听器调用的入口public void lifecycleEvent(LifecycleEvent event){if (event.getType().equals(Lifecycle.CONFIGURE_START_EVENT)) {//根据入参&#xff0c;会走到该分支configureStart();} else if (event.getType().equals(Lifecycle.BEFORE_START_EVENT)) {beforeStart();} else if (event.getType().equals(Lifecycle.AFTER_START_EVENT)) {// Restore docBase for management toolsif (originalDocBase !&#61; null) {context.setDocBase(originalDocBase);}} ...}protected synchronized void configureStart() {// Called from StandardContext.start()//调用此处方法webConfig();}protected void webConfig() {//xml解析器WebXmlParser webXmlParser &#61; new WebXmlParser(context.getXmlNamespaceAware(),context.getXmlValidation(), context.getXmlBlockExternal());Set<WebXml> defaults &#61; new HashSet<>();defaults.add(getDefaultWebXmlFragment(webXmlParser));//创建web.xml格式的对象&#xff0c;此时属性都为空WebXml webXml &#61; createWebXml(); // 创建web.xml文件流InputSource contextWebXml &#61; getContextWebXmlSource();//解析流&#xff0c;把内容封装到webXmlif (!webXmlParser.parseWebXml(contextWebXml, webXml, false)) {ok &#61; false;}//处理web-fragment.xml文件&#xff0c;分多个步骤//Step 1. 扫描/META-INF/lib/目录下的jar文件&#xff0c;如果在META-INF下含有web-fragment.xml文件&#xff0c;解析它Map<String,WebXml> fragments &#61; processJarsForWebFragments(webXml, webXmlParser);// Step 2. 确定确定这些xml片段的顺序Set<WebXml> orderedFragments &#61; null;orderedFragments &#61;WebXml.orderWebFragments(webXml, fragments, sContext);// Step 3. 处理ServletContainerInitializers的实现类if (ok) {processServletContainerInitializers();}if (!webXml.isMetadataComplete() || typeInitializerMap.size() > 0) {// Steps 4 & 5 都在processClasses里面&#xff0c;提前讲下//Steps 4 处理/WEB-INF/classes 下的注解类和 &#64;HandlesTypes matches//Steps 5 处理 引入的JARs中的注解类和 &#64;HandlesTypes matchesprocessClasses(webXml, orderedFragments);}if (!webXml.isMetadataComplete()) {// Step 6. 将应用中的web.xml与orderedFragments进行合并&#xff0c;合并在WebXml类的merge方法中实现if (ok) {ok &#61; webXml.merge(orderedFragments);}// Step 7. 将应用中的web.xml与全局的web.xml文件&#xff08;conf/web.xml和web.xml.default&#xff09;进行合并// Have to merge defaults before JSP conversion since defaults// provide JSP servlet definition.webXml.merge(defaults);// Step 8. Convert explicitly mentioned jsps to servletsif (ok) {convertJsps(webXml);}// Step 9. 通过webXml对象&#xff0c;间接把web.xml构建成 Context对象if (ok) {configureContext(webXml);}}

1、扫描/META-INF/lib/目录下的jar文件&#xff0c;如果在META-INF下含有web-fragment.xml文件&#xff0c;解析它&#xff1b;
2、确定确定这些xml片段的顺序
3、处理ServletContainerInitializers的实现类
4、将应用中的web.xml与orderedFragments进行合并&#xff0c;合并在WebXml类的merge方法中实现
5、将应用中的web.xml与全局的web.xml文件&#xff08;conf/web.xml和web.xml.default&#xff09;进行合并
6、用合并好的WebXml来配置Context&#xff0c;这一步在处理servlet时&#xff0c;会为每个servlet创建一个wrapper&#xff0c;并调用addChild将每个wrapper作为context子容器&#xff0c;后续分析

2.1 web-fragment.xml知识

servlet 3.0可以将配置文件分散在多个jar包里面&#xff0c;而且还可以定义这些配置文件的顺序。分为绝对顺序和相对顺序&#xff0c;绝对顺序是通过absolute-ordering标签定义的&#xff1a;

<web-app><name>...</name><absolute-ordering><name>fragment1</name><name>fragment2</name></absolute-ordering></web-app>

还可以在web-fragment.xml里面通过before,after标签来定义这些配置文件的先后顺序&#xff0c;这里不再举例这步主要是根据顺序&#xff0c;将这些配置文件加到集合orderedFragments中。

2.2 ServletContainerInitializers的实现类

这也是servlet 3.0新增的特性&#xff0c;容器在启动时使用 JAR 服务 API(JAR Service API) 来发现 ServletContainerInitializer 的实现类&#xff0c;并且容器将 WEB-INF/lib 目录下 JAR 包中的类都交给该类的 onStartup() 方法处理&#xff0c;我们通常需要在该实现类上使用 &#64;HandlesTypes 注解来指定希望被处理的类&#xff0c;过滤掉不希望给 onStartup() 处理的类。

在onStartup方法中可以优先加载这些类&#xff0c;或者修改其中的方法等。这步主要是把这些类找到放到Set scis中&#xff0c;进而放入typeInitializerMap&#xff1b;

protected void processServletContainerInitializers() {Set<ServletContainerInitializer> scis &#61;typeInitializerMap.get(type);if (scis &#61;&#61; null) {scis &#61; new HashSet<>();typeInitializerMap.put(type, scis);}scis.add(sci);

2.3 web.xml文件加载的细节

只要知道了web.xml加载路径信息即可&#xff1a;
在这里插入图片描述

参考&#xff1a;《Tomcat学习之ContextConfig》


推荐阅读
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 本文介绍了如何使用C#制作Java+Mysql+Tomcat环境安装程序,实现一键式安装。通过将JDK、Mysql、Tomcat三者制作成一个安装包,解决了客户在安装软件时的复杂配置和繁琐问题,便于管理软件版本和系统集成。具体步骤包括配置JDK环境变量和安装Mysql服务,其中使用了MySQL Server 5.5社区版和my.ini文件。安装方法为通过命令行将目录转到mysql的bin目录下,执行mysqld --install MySQL5命令。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • ASP.NET2.0数据教程之十四:使用FormView的模板
    本文介绍了在ASP.NET 2.0中使用FormView控件来实现自定义的显示外观,与GridView和DetailsView不同,FormView使用模板来呈现,可以实现不规则的外观呈现。同时还介绍了TemplateField的用法和FormView与DetailsView的区别。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • 本文介绍了在rhel5.5操作系统下搭建网关+LAMP+postfix+dhcp的步骤和配置方法。通过配置dhcp自动分配ip、实现外网访问公司网站、内网收发邮件、内网上网以及SNAT转换等功能。详细介绍了安装dhcp和配置相关文件的步骤,并提供了相关的命令和配置示例。 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文介绍了在使用Python中的aiohttp模块模拟服务器时出现的连接失败问题,并提供了相应的解决方法。文章中详细说明了出错的代码以及相关的软件版本和环境信息,同时也提到了相关的警告信息和函数的替代方案。通过阅读本文,读者可以了解到如何解决Python连接服务器失败的问题,并对aiohttp模块有更深入的了解。 ... [详细]
  • 标题: ... [详细]
  • 开发笔记:Java是如何读取和写入浏览器Cookies的
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了Java是如何读取和写入浏览器Cookies的相关的知识,希望对你有一定的参考价值。首先我 ... [详细]
  • 本文介绍了在Linux下安装和配置Kafka的方法,包括安装JDK、下载和解压Kafka、配置Kafka的参数,以及配置Kafka的日志目录、服务器IP和日志存放路径等。同时还提供了单机配置部署的方法和zookeeper地址和端口的配置。通过实操成功的案例,帮助读者快速完成Kafka的安装和配置。 ... [详细]
author-avatar
谢海武181_160
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有