- 浏览: 132100 次
- 性别:
- 来自: ...
文章分类
最新评论
上一篇文章只是很简单的跟踪了tomcat启动的主线(因为刚刚看代码,所以不可能一下子全部都看的懂,比较菜),本次把最近看到的一些新的内容和领悟继续分享一下,本次关心的主题是tomcat是怎么启动的时候部署webapp下面的每一个web应用的?
前面的启动分析在之前的文章中有介绍,直接从Catalina开始看起。在此先说明一点,即将出场的:StandardEngine,StandardHost,StandardContext都是继承自ContainerBase的容器类。
1. Catalina的load()方法会调用Digester的parse()解析相关的xml文件并且根据不同的Rule映射对应的Bean,其中映射到的StandardEngine实例会根据相应的Rule反射调用其父类addChild(Container child)把StandardHost加入到children的map中,而映射到的StandardService实例会根据相应的Rule反射调用其setContainer(Container container)把StandardEngine赋值给StandService的container属性,这样完成了热身运动。
2. 接着就是Catalina(start)-->StandardServer(start)-->StandardService(start)-->StandardEngine(start),到达此处还没有开始任何部署的主要工作,此时进入父类StandardEngine[ContainerBase].start()方法:
部分代码:
这里的children[]数组里面就是之前的StandardHost类的实例,代码的走向: StandardEngine[name=Catalina,method=start]--> StandardHost[name=localhost,method=start],好戏就要开始了...
3. 继续之前,先说一下这部分的设计思路。基本上就是Observer模式主导,容器类通过addLifecycleListener方法调用事件发布辅助类LifecycleSupport的addLifecycleListener方法注册listener,同时LifecycleSupport提供方法fireLifecycleEvent给各个已注册的listener发送事件通知,主要是给*Config的类,例如:EngineConfig,HostConfig,ContextConfig等等。通过这些listener的lifecycleEvent方法响应事件。
言归正传,进入StandardHost的start方法首先要先执行init方法初始化,在这个过程中:
部分代码:
注册了一个关键的listener,初始化完毕后,继续执行start进入容器父类ContainerBase的start方法使用其LifecycleSupport实例变量发送通知lifecycle.fireLifecycleEvent(START_EVENT, null);此时的listener实例HostConfig接收消息进行处理执行到if(event.getType().equals(Lifecycle.START_EVENT)) start();进入其自身的start()方法继续执行,直到if (host.getDeployOnStartup()) deployApps();进入deployApps方法:
所有要部署的web应用都是通过这个方法进行部署。下面以我的webapp为例(包含host-manager应用)进行说明。
4. 首先是deployDescriptors(File configBase, String[] files)其中files里面包含了host-manager.xml,该文件就是位于/conf/Catalina/localhost/下,接着就是在以files长度循环内调用deployDescriptor(String contextPath, File contextXml, String file)分别的部署各个应用。此方法有如下代码片断:
这里的context对应web应用的StandardContext,host当然就是前两级容器StandardEngine[Catalina].StandardHost[localhost],而listener就是对应的ContextConfig。当执行host.addChild(context);时会跑到StandardHost的父类ContainerBase的addChild(Container child)-->addChildInternal(Container child),在这个方法里,作为child的StandardContext[/host-manager]除了被添加成三级子容器之外,调用了它的start方法。
5. 在StandardContext start里,lifecycle.fireLifecycleEvent(START_EVENT, null);又出现了!只好进入其对应的listener实例ContextConfig。它的事件处理也是类似的if (event.getType().equals(Lifecycle.START_EVENT)) start();只好再进入其start方法:
在这个方法里处理了webapp下host-manager应用的web.xml文件等等。完毕之后现在的容器就成了StandardEngine[Catalina].StandardHost[localhost].StandardContext[/host-manager],然后有多少应用就生成多少三级容器。
6. 其他的web应用的部署方式类似。每一个最终的容器Context,都有一个StandardWrapper,它本身也是一个容器但是不允许再有子容器了。本例对应的就是StandardWrapper[host-manager],这个东东就是负责对每个servlet的生命周期进行管理,同时管理其请求响应等等。
至此,我想关于tomcat的启动的分析应该可以算入门了。其实看源码具体的类的实现的代码不见得处处放光,很多都是一般般的实现。但是每个模块的设计,解藕和衔接是我一直想追求的技能,简简单单的代码组合在一起就成为一个变形金刚。希望能从中得到更多的启发,分享更多。
前面的启动分析在之前的文章中有介绍,直接从Catalina开始看起。在此先说明一点,即将出场的:StandardEngine,StandardHost,StandardContext都是继承自ContainerBase的容器类。
1. Catalina的load()方法会调用Digester的parse()解析相关的xml文件并且根据不同的Rule映射对应的Bean,其中映射到的StandardEngine实例会根据相应的Rule反射调用其父类addChild(Container child)把StandardHost加入到children的map中,而映射到的StandardService实例会根据相应的Rule反射调用其setContainer(Container container)把StandardEngine赋值给StandService的container属性,这样完成了热身运动。
2. 接着就是Catalina(start)-->StandardServer(start)-->StandardService(start)-->StandardEngine(start),到达此处还没有开始任何部署的主要工作,此时进入父类StandardEngine[ContainerBase].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(); } ...
这里的children[]数组里面就是之前的StandardHost类的实例,代码的走向: StandardEngine[name=Catalina,method=start]--> StandardHost[name=localhost,method=start],好戏就要开始了...
3. 继续之前,先说一下这部分的设计思路。基本上就是Observer模式主导,容器类通过addLifecycleListener方法调用事件发布辅助类LifecycleSupport的addLifecycleListener方法注册listener,同时LifecycleSupport提供方法fireLifecycleEvent给各个已注册的listener发送事件通知,主要是给*Config的类,例如:EngineConfig,HostConfig,ContextConfig等等。通过这些listener的lifecycleEvent方法响应事件。
言归正传,进入StandardHost的start方法首先要先执行init方法初始化,在这个过程中:
部分代码:
... HostConfig deployer = new HostConfig(); addLifecycleListener(deployer); ...
注册了一个关键的listener,初始化完毕后,继续执行start进入容器父类ContainerBase的start方法使用其LifecycleSupport实例变量发送通知lifecycle.fireLifecycleEvent(START_EVENT, null);此时的listener实例HostConfig接收消息进行处理执行到if(event.getType().equals(Lifecycle.START_EVENT)) start();进入其自身的start()方法继续执行,直到if (host.getDeployOnStartup()) deployApps();进入deployApps方法:
protected void deployApps() { File appBase = appBase(); File configBase = configBase(); // Deploy XML descriptors from configBase deployDescriptors(configBase, configBase.list()); // Deploy WARs, and loop if additional descriptors are found deployWARs(appBase, appBase.list()); // Deploy expanded folders deployDirectories(appBase, appBase.list()); }
所有要部署的web应用都是通过这个方法进行部署。下面以我的webapp为例(包含host-manager应用)进行说明。
4. 首先是deployDescriptors(File configBase, String[] files)其中files里面包含了host-manager.xml,该文件就是位于/conf/Catalina/localhost/下,接着就是在以files长度循环内调用deployDescriptor(String contextPath, File contextXml, String file)分别的部署各个应用。此方法有如下代码片断:
... if (context instanceof Lifecycle) { Class clazz = Class.forName(host.getConfigClass()); LifecycleListener listener = (LifecycleListener) clazz.newInstance(); ((Lifecycle) context).addLifecycleListener(listener); } ... host.addChild(context); ...
这里的context对应web应用的StandardContext,host当然就是前两级容器StandardEngine[Catalina].StandardHost[localhost],而listener就是对应的ContextConfig。当执行host.addChild(context);时会跑到StandardHost的父类ContainerBase的addChild(Container child)-->addChildInternal(Container child),在这个方法里,作为child的StandardContext[/host-manager]除了被添加成三级子容器之外,调用了它的start方法。
5. 在StandardContext start里,lifecycle.fireLifecycleEvent(START_EVENT, null);又出现了!只好进入其对应的listener实例ContextConfig。它的事件处理也是类似的if (event.getType().equals(Lifecycle.START_EVENT)) start();只好再进入其start方法:
... // Process the default and application web.xml files defaultWebConfig(); applicationWebConfig(); ...
在这个方法里处理了webapp下host-manager应用的web.xml文件等等。完毕之后现在的容器就成了StandardEngine[Catalina].StandardHost[localhost].StandardContext[/host-manager],然后有多少应用就生成多少三级容器。
6. 其他的web应用的部署方式类似。每一个最终的容器Context,都有一个StandardWrapper,它本身也是一个容器但是不允许再有子容器了。本例对应的就是StandardWrapper[host-manager],这个东东就是负责对每个servlet的生命周期进行管理,同时管理其请求响应等等。
至此,我想关于tomcat的启动的分析应该可以算入门了。其实看源码具体的类的实现的代码不见得处处放光,很多都是一般般的实现。但是每个模块的设计,解藕和衔接是我一直想追求的技能,简简单单的代码组合在一起就成为一个变形金刚。希望能从中得到更多的启发,分享更多。
发表评论
文章已被作者锁定,不允许评论。
-
一道位操作的趣味编程题
2010-03-14 10:50 2124看到一道很有意思的编程题:大厅里有64盏灯,每盏灯都编 ... -
一道字符串截取的编程题
2010-03-11 10:52 2321最近接触到一道字符串截取的编程题:编写一个截取字符串的 ... -
一道多线程趣味热身题
2010-02-28 18:01 1960保持对知识点或者技术的熟悉度对于程序员至关重要,要学会 ... -
疑似Google多线程面试题的Java实现
2010-02-24 17:39 4965来到一个完全陌生的地方,即将一切从新开始,内心兴奋又忐 ... -
Mina的线程池实现分析(2)
2010-02-10 17:31 4590分析了I/O事件的存储,下面看看多个Worker同时工 ... -
Mina的线程池实现分析(1)
2010-02-10 17:28 11633线程池是并发应用中,为了减少每个任务调用的开销增强性能 ... -
多线程基础总结十一--ConcurrentLinkedQueue
2010-02-03 17:52 12952ConcurrentLinkedQueue充分使用了a ... -
LinkedBlockingQueue应用--生产消费模型简单实现
2010-01-29 20:45 8213之前介绍时LinkedBlockingQueue提到了 ... -
多线程基础总结十--LinkedBlockingQueue
2010-01-28 14:33 15443随着多线程基础总结的增多,却明显的感觉知道的越来越少, ... -
号称放倒一片的一道J2SE基础题的个人理解
2010-01-23 14:07 2847近日无意中看到一道Java基础题,号称在接受测试的10 ... -
多线程基础总结九--Mina窥探(1)
2010-01-21 23:46 5455一直以来的多线程的基础总结都是脱离应用的,但是要说多线 ... -
多线程基础总结八--ReentrantReadWriteLock
2010-01-15 23:22 7559说到ReentrantReadWriteLock,首先 ... -
多线程基础总结七--ReentrantLock
2010-01-09 23:17 7731之前总结了部分无锁机制的多线程基础,理想的状态当然是利 ... -
关于atomic问题的一点理解
2009-12-30 16:42 2488之前看到一个帖子是关于atomic使用的,当时没有仔细 ... -
多线程基础总结六--synchronized(2)
2009-12-18 18:45 1913早在总结一时,我就尽量的把synchronized的重点 ... -
多线程基础总结五--atomic
2009-12-17 19:46 3596在简单介绍java.util.c ... -
多线程基础总结四--ThreadLocal
2009-12-16 19:48 2765说到ThreadLocal,首先 ... -
多线程基础总结三--volatile
2009-12-15 20:09 2585前面的两篇总结简 ... -
多线程基础总结二--Thread
2009-12-12 23:27 2713对于Thread来说 ... -
多线程基础总结一--synchronized(1)
2009-12-12 23:23 3118最近写关于并发的小应 ...
相关推荐
这个源码包,"apache-tomcat-6.0.43-src",是Tomcat 6的官方源代码,非常适合开发者进行深入学习和自定义修改。以下是基于这个源码包的一些关键知识点: 1. **Servlet容器**:Tomcat作为Servlet容器,其主要任务是...
【标题】"Tomcat6的源码"涵盖了Java Web服务器Apache Tomcat的第六个主要版本的源代码。这个版本在2005年发布,它为开发者提供了深入了解Servlet和JSP容器工作原理的机会,同时也支持Java EE 5规范。Tomcat6是开源...
MyEclipse会通过源码编译并启动Tomcat,你可以在"Console"视图中观察启动日志,确认服务器是否成功运行。 在深入研究Tomcat源码时,理解其模块结构和主要组件是非常重要的。Tomcat的主要组件包括Catalina(核心...
《深入理解Tomcat6启动脚本》 在Java Web应用领域,Tomcat作为一个流行的开源Servlet容器,被广泛用于部署和管理Web应用程序。然而,要确保Tomcat顺利运行,正确理解和配置启动脚本至关重要。本文将详细解析Tomcat6...
《深入剖析Tomcat 6与7的源码》 Tomcat作为开源的Java Servlet容器,是许多Web开发者和系统管理员的首选。它以其轻量级、高效和易于配置的特性赢得了广泛赞誉。本文将深入探讨Tomcat 6和7的源码,揭示其内部工作...
《Tomcat6源码分析——深入理解Web服务器的运行机制》 Tomcat6作为Apache软件基金会的Jakarta项目的一部分,是一款广泛使用的Java Servlet容器,它实现了Java Servlet和JavaServer Pages(JSP)规范,为开发和部署...
二、Tomcat7启动流程 1. Bootstrap:启动过程始于Bootstrap类,它加载并初始化Server对象。 2. Server:Server对象包含了全局配置信息,并管理Service组件。 3. Service:Service包含一个或多个Connector(如...
《深入剖析Tomcat 6.0源码》 Tomcat,作为开源的Java Servlet容器,是许多Web开发者和系统管理员的首选。Tomcat 6.0版本是它的一个经典版本,提供了对Servlet 2.5和JSP 2.1规范的支持。本文将围绕Tomcat 6.0源码...
《深入剖析Tomcat6源码》 Tomcat6是一款经典的开源Java Servlet容器,它作为Apache软件基金会项目的一部分,被广泛用于部署Web应用程序。本篇将深入探讨Tomcat6的源码,揭示其内部运行机制,帮助开发者理解Web...
《深入剖析Tomcat7源码》 Tomcat7是一款广泛使用的开源Java Servlet容器,它实现了Java EE中的Servlet和JSP规范。源码分析是提升开发者对服务器内部运作机制理解的重要途径,尤其对于Tomcat这样的核心组件,源码的...
二、Idea配置运行Tomcat源码 在IntelliJ IDEA中运行Tomcat源码,我们需要进行以下步骤: 1. 下载Tomcat源码:可以从Apache官网获取Tomcat 6的源码包,例如这里我们使用的是apache-tomcat-6.0.44-study。 2. 导入...
Apache Tomcat 8.5.23 源码分析 Apache Tomcat 是一个开源的、免费的Web服务器和Servlet容器,它实现了Java Servlet和JavaServer Pages(JSP)规范,是开发和部署Java Web应用的重要平台。深入理解Tomcat的源码有助...
3-6Tomcat处理源码实现与异步Servlet源码实现(1).mp4
《深入剖析Tomcat 7.0.42源码》 Tomcat,作为Apache软件基金会的一个开源项目,是Java Servlet和JavaServer Pages(JSP)技术的流行应用服务器,广泛应用于各类Web应用的部署和开发。7.0.42版本是Tomcat发展中的一...
【标题】"Tomcat6 编译好的源码"指的是Apache Tomcat服务器的第六个主要版本的源代码,已经经过编译过程,可以直接用于开发或学习。Tomcat是一款开源的Java Servlet容器,它实现了Java EE的Web应用服务规范,如...
《深入理解MyEclipse下Tomcat_7.0.78源码运行机制》 Tomcat作为一款广泛应用的开源Web服务器和Servlet容器,其源码分析对于Java Web开发者来说具有极高的学习价值。本篇文章将重点围绕"MyEclipse下Tomcat_7.0.78...
这个资源包包含了Tomcat的源码、文档以及源码解析,对于深入理解Tomcat的工作原理、优化应用性能以及进行二次开发具有极大的帮助。 首先,让我们深入探讨Tomcat的源码。源码是软件的基石,通过阅读源码,我们可以...
《深入解析Tomcat线程池源码》 Tomcat作为一款广泛应用的开源Servlet容器,其在性能优化上有着独到之处。线程池是Tomcat处理并发请求的关键组件,它负责调度和管理线程,有效地提高了服务器的响应速度和并发处理...
tomcat 开机启动,dos窗口去掉,tomcat 开机启动,dos窗口去掉
标题中的“tomcat6开机启动”指的是在操作系统启动时,能够自动运行Tomcat 6.0.33服务器,使得用户无需手动开启服务,提高工作效率。Tomcat是Apache软件基金会的Jakarta项目中的一个核心项目,它是一个开源的Java ...