tomcat源码剖析
最近看Tomcat的源码的节奏还算是挺紧凑的,给人的感觉,tomcat的代码相对以前读的jetty的代码显得更有条理一些。。。当然这也是有可能是因为自己看的jetty的版本是比较老的,而看的Tomcat的代码却是比较新的Tomcat8的代码。。。。
好了闲话不多说了。。。
先来说说LifeCycle的概念。。。
这个在jetty中也有,组要是用于维护一个组件的生命周期,例如start,stop啥的。。。
另外对于有lifecycle概念的组件,一般也都还有listener的概念,当组件的状态发生改变的时候,可以有listener进行响应。。。
好啦先来看看最上层的LifeCycle接口的定义吧:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
//生命周期的接口定义 public interface Lifecycle { //下面定义了一些基本的状态 public static final String BEFORE_INIT_EVENT = "before_init" ; /** * The LifecycleEvent type for the "component after init" event. */ public static final String AFTER_INIT_EVENT = "after_init" ; /** * The LifecycleEvent type for the "component start" event. */ public static final String START_EVENT = "start" ; /** * The LifecycleEvent type for the "component before start" event. */ public static final String BEFORE_START_EVENT = "before_start" ; /** * The LifecycleEvent type for the "component after start" event. */ public static final String AFTER_START_EVENT = "after_start" ; /** * The LifecycleEvent type for the "component stop" event. */ public static final String STOP_EVENT = "stop" ; /** * The LifecycleEvent type for the "component before stop" event. */ public static final String BEFORE_STOP_EVENT = "before_stop" ; /** * The LifecycleEvent type for the "component after stop" event. */ public static final String AFTER_STOP_EVENT = "after_stop" ; /** * The LifecycleEvent type for the "component after destroy" event. */ public static final String AFTER_DESTROY_EVENT = "after_destroy" ; /** * The LifecycleEvent type for the "component before destroy" event. */ public static final String BEFORE_DESTROY_EVENT = "before_destroy" ; /** * The LifecycleEvent type for the "periodic" event. */ public static final String PERIODIC_EVENT = "periodic" ; public static final String CONFIGURE_START_EVENT = "configure_start" ; public static final String CONFIGURE_STOP_EVENT = "configure_stop" ; // --------------------------------------------------------- Public Methods /** * Add a LifecycleEvent listener to this component. * * @param listener The listener to add */ //添加一个监听器 public void addLifecycleListener(LifecycleListener listener); /** * Get the life cycle listeners associated with this life cycle. If this * component has no listeners registered, a zero-length array is returned. */ //返回所有的监听器 public LifecycleListener[] findLifecycleListeners(); /** * Remove a LifecycleEvent listener from this component. * * @param listener The listener to remove */ //移除一个监听器 public void removeLifecycleListener(LifecycleListener listener); //初始化 public void init() throws LifecycleException; //启动 public void start() throws LifecycleException; //停止 public void stop() throws LifecycleException; /** * Prepare to discard the object. The following {@link LifecycleEvent}s will * be fired in the following order: * <ol> * <li>DESTROY_EVENT: On the successful completion of component * destruction.</li> * </ol> * * @exception LifecycleException if this component detects a fatal error * that prevents this component from being used */ //销毁 public void destroy() throws LifecycleException; /** * Obtain the current state of the source component. * * @return The current state of the source component. */ //返回当前的生命周期状态 public LifecycleState getState(); /** * Obtain a textual representation of the current component state. Useful * for JMX. */ //返回状态的名字 public String getStateName(); } |
还是比较简单的吧,先是一些基本的状态和事件的定义,然后接下来是一些基本的操作,例如添加listener,移除listener,启动,停止什么的。。都还算比较的常规。。。
接下来是LifeCycle的抽象层,LifecycleBase。。。
这里就不具体的体贴出它的实现代码了,。。。LifecycleBase直接继承自LifeCycle接口,这里主要是实现了中间添加listener,移除listener的操作,这里可以可以初步理解为这里扩展成了一个listener的容器。。
另外LifecycleBase的定义中,还扩展了基本的启动,停止操作什么的。。。
例如当组件启动的时候,就需要更改当前组件的状态,并调用相应的listener。。。这里就拿初始化的方法来举例子吧:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
//这里扩展了init方法,这里首先设置当前组件的状态, @Override public final synchronized void init() throws LifecycleException { if (!state.equals(LifecycleState.NEW)) { invalidTransition(Lifecycle.BEFORE_INIT_EVENT); } setStateInternal(LifecycleState.INITIALIZING, null , false ); //设置当前的状态为INITIALIZING try { initInternal(); //调用该方法用于初始化,具体的实现在子类中 } catch (Throwable t) { ExceptionUtils.handleThrowable(t); setStateInternal(LifecycleState.FAILED, null , false ); throw new LifecycleException( sm.getString( "lifecycleBase.initFail" ,toString()), t); } setStateInternal(LifecycleState.INITIALIZED, null , false ); //将对象设置为INITIALIZED状态 } //具体初始化的方法啊,在子类中实现 protected abstract void initInternal() throws LifecycleException; |
这里应该代码很容易能理解吧,无非就是对当前组件的装填进行验证,并修改组件的状态,当然在设置组件的状态的时候还伴随着对listener的调用。。。
最后再调用initInternal方法进行初始化,当然这个方法需要在具体的子类中进行实现。。。。
另外这里还要介绍一个比较特殊的LifeCycle的抽象层,LifecycleMBeanBase,它继承了抽象类LifecycleBase类型,其实这里看名字就能够知道这个抽象层要干些啥事情了吧。。。。来看一段代码:
1
2
3
4
5
6
7
8
9
10
|
protected void initInternal() throws LifecycleException { // If oname is not null then registration has already happened via // preRegister(). if (oname == null ) { mserver = Registry.getRegistry( null , null ).getMBeanServer(); //获取用到的mbserver oname = register( this , getObjectNameKeyProperties()); //注册当前组件到mbserver } } |
嗯,其实就是在组件的初始化的时候对当前组件在JMX上进行注册,具体Tomcat的JMX部分内容,在前面的文章中就已经说过了,这里就不详细说了。。。
也就是说,如果一个类型需要在JMX上进行注册,那么它需要继承LifeCycleMBeanBase抽象类,然后实现其中的几个抽象方法。。。
好啦,到这里位置,LifeCycle部分的内容就算差不多了。。
总的感觉,Tomcat在LifeCycle部分的设计还算是比较简单的。。。。
好啦,接下来来看看Server部分的内容吧。。。首先来看看最顶层的接口的定义:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
package org.apache.catalina; import java.io.File; import org.apache.catalina.deploy.NamingResourcesImpl; import org.apache.catalina.startup.Catalina; //顶层的server接口的定义,继承了生命周期接口 public interface Server extends Lifecycle { // ------------------------------------------------------------- Properties /** * Return the global naming resources. */ public NamingResourcesImpl getGlobalNamingResources(); /** * Set the global naming resources. * * @param globalNamingResources The new global naming resources */ public void setGlobalNamingResources (NamingResourcesImpl globalNamingResources); /** * Return the global naming resources context. */ public javax.naming.Context getGlobalNamingContext(); /** * Return the port number we listen to for shutdown commands. */ public int getPort(); //用于监听shutdown命令的端口 /** * Set the port number we listen to for shutdown commands. * * @param port The new port number */ public void setPort( int port); ////用于监听shutdown命令的端口 /** * Return the address on which we listen to for shutdown commands. */ public String getAddress(); //用于监听shutdown命令的地址 /** * Set the address on which we listen to for shutdown commands. * * @param address The new address */ public void setAddress(String address); //用于监听shutdown命令的地址 /** * Return the shutdown command string we are waiting for. */ public String getShutdown(); /** * Set the shutdown command we are waiting for. * * @param shutdown The new shutdown command */ public void setShutdown(String shutdown); public ClassLoader getParentClassLoader(); //这个server对象用的classLoader,一般是catalina loader public void setParentClassLoader(ClassLoader parent); public Catalina getCatalina(); //获取catalina对象 public void setCatalina(Catalina catalina); //设置用的catalina对象 public File getCatalinaBase(); //一般情况下都是tomcat的根路径 public void setCatalinaBase(File catalinaBase); public File getCatalinaHome(); public void setCatalinaHome(File catalinaHome); public void addService(Service service); //添加service对象 public void await(); public Service findService(String name); //根据名字获取某个service public Service[] findServices(); //获取所有的service public void removeService(Service service); //删除一个service } |
嗯,其实最顶层的Server接口的定义也很简单,扩展了lifeCycle接口其中最重要的部分无非是对service的添加以及移除。。。
给人最大的干吼就是它是一个service的容器
好啦,接下来来看看最常用的类型StandardServer吧,这里它不光实现了Server接口,还继承了LifecycleMBeanBase类型,这里也就表示StandardServer将会被注册到JMX上面去的。。。
由于它的代码比较长,这里就不直接贴出来了。。来比较重要的属性定义吧:
1
2
|
private Service services[] = new Service[ 0 ]; //用于保存所有的service,是一个数组啊 private final Object servicesLock = new Object(); |
嗯,一个service的数组。。。。嗯,容器嘛。。。
好了,这里也就稍微的来看看初始话和启动两个方法的实现吧:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
|
protected void initInternal() throws LifecycleException { super .initInternal(); //父类的init,它里面主要是进行对象在mbserver上面注册当前对象 // Register global String cache // Note although the cache is global, if there are multiple Servers // present in the JVM (may happen when embedding) then the same cache // will be registered under multiple names onameStringCache = register( new StringCache(), "type=StringCache" ); // Register the MBeanFactory MBeanFactory factory = new MBeanFactory(); //创建MBeanFactory factory.setContainer( this ); //设置当前mbeanfactory的container onameMBeanFactory = register(factory, "type=MBeanFactory" ); //注册mbeanfactory // Register the naming resources globalNamingResources.init(); //初始计划名字资源 // Populate the extension validator with JARs from common and shared // class loaders if (getCatalina() != null ) { //获取catalina对象 ClassLoader cl = getCatalina().getParentClassLoader(); //在bootstrap里面设置成了shareloader // Walk the class loader hierarchy. Stop at the system class loader. // This will add the shared (if present) and common class loaders //加载classLoader里面的路径的资源,这里会向上遍历classLoader while (cl != null && cl != ClassLoader.getSystemClassLoader()) { if (cl instanceof URLClassLoader) { URL[] urls = ((URLClassLoader) cl).getURLs(); for (URL url : urls) { if (url.getProtocol().equals( "file" )) { try { File f = new File (url.toURI()); if (f.isFile() && f.getName().endsWith( ".jar" )) { ExtensionValidator.addSystemResource(f); } } catch (URISyntaxException e) { // Ignore } catch (IOException e) { // Ignore } } } } cl = cl.getParent(); } } // Initialize our defined Services for ( int i = 0 ; i < services.length; i++) { //初始化service services[i].init(); } } |
首先是初始化,这里最重要的事情其实是对当前包含的所有的service的初始化,另外还有一些其他的操作,注释应该也算是交代的比较清楚吧。。。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
//父类中定义的抽象方法扩展了lifecycle的start方法,用于启动当前的对象,这里月就是启动tomcat,其实是启动server的service @Override protected void startInternal() throws LifecycleException { fireLifecycleEvent(CONFIGURE_START_EVENT, null ); setState(LifecycleState.STARTING); globalNamingResources.start(); // Start our defined Services synchronized (servicesLock) { for ( int i = 0 ; i < services.length; i++) { //遍历当前的service,然后启动他们 services[i].start(); } } } |
启动方法,这里其实最主要的也还是对Service的启动。。。
tomcat源码剖析的更多相关文章
- tomcat源码剖析系列
一个简单的web服务器 一个简单的servlet容器 连接器 创建httpRequest 创建HttpResponse 容器 生命周期 日志记录器 载入器 Session管理 关闭钩子 启动tomca ...
- 75篇关于Tomcat源码和机制的文章
75篇关于Tomcat源码和机制的文章 标签: tomcat源码机制 2016-12-30 16:00 10083人阅读 评论(1) 收藏 举报 分类: tomcat内核(82) 版权声明:本文为 ...
- Tomcat源码分析--转
一.架构 下面谈谈我对Tomcat架构的理解 总体架构: 1.面向组件架构 2.基于JMX 3.事件侦听 1)面向组件架构 tomcat代码看似很庞大,但从结构上看却很清晰和简单,它主要由一堆组件组成 ...
- ThreadLocal终极源码剖析
目录一.ThreadLocal1.1 源码注释1.2 源码剖析 散列算法-魔数0x61c88647 set操作 get操作 remove操作1.3 功能测试1.4 应用 ...
- ThreadLocal终极源码剖析-一篇足矣!
本文较深入的分析了ThreadLocal和InheritableThreadLocal,从4个方向去分析:源码注释.源码剖析.功能测试.应用场景. 一.ThreadLocal 我们使用ThreadLo ...
- Tomcat源码解析-整体流程介绍
一.架构 下面谈谈我对Tomcat架构的理解 总体架构: 1.面向组件架构 2.基于JMX 3.事件侦听 1)面向组件架构 tomcat代码看似很庞大,但从结构上看却很清晰和简单,它主要由一堆组件组成 ...
- Tomcat源码分析——请求原理分析(下)
前言 本文继续讲解TOMCAT的请求原理分析,建议朋友们阅读本文时首先阅读过<TOMCAT源码分析——请求原理分析(上)>和<TOMCAT源码分析——请求原理分析(中)>.在& ...
- Tomcat源码分析——请求原理分析(上)
前言 谈起Tomcat的诞生,最早可以追溯到1995年.近20年来,Tomcat始终是使用最广泛的Web服务器,由于其使用Java语言开发,所以广为Java程序员所熟悉.很多人早期的J2EE项目,由程 ...
- Tomcat源码分析——启动与停止服务
前言 熟悉Tomcat的工程师们,肯定都知道Tomcat是如何启动与停止的.对于startup.sh.startup.bat.shutdown.sh.shutdown.bat等脚本或者批处理命令,大家 ...
随机推荐
- ST第三次作业Junit安装
一.Junit安装 安装eclipse,右键“项目”文件——>java build path——>导入jar包junit-4.12.jar和hamcrest-all-1.3.jar包. 二 ...
- QML Image: Cannot open: qrc:///new.pic.png
初次遇到这个问题真有点摸不着头脑,于是乎百度一下咯,但是百度一向没有什么用,该有的没有,没用的回答倒是有特么一大堆. 自己解决: 我的解决方法很简答: 第一步:把图片放到当前路径下,也就是和.pro一 ...
- html页面元素事件丢失
前段时间做网站包括最近用mvc做oa都发现这个奇怪现象,就是页面加载完毕后页面元素事件(比如按钮点击.复选框change)一切正常,但是当执行查询或者其他操作后页面事件丢失.具体原因暂没有时间分析,现 ...
- codeforces A. Difference Row
link:http://codeforces.com/contest/347/problem/A 开始看起来很复杂的样子,但是刚写下样例,就发现因为中间的都消去了,其实起作用的就是最大值和最小值=_= ...
- pyspider 简单应用之快速问医生药品抓取(一)
网址:http://yp.120ask.com/search/-0-0--0-0-0-0.html from pyspider.libs.base_handler import * class Han ...
- About Flash
Take SAMSUNG K9F1G08U0E for example, and use S3C2416, Windows CE5.0 platform. 要让Flash工作起来,包括两部分: Fla ...
- [NOIP2015] 斗地主(搜索)
题目描述 牛牛最近迷上了一种叫斗地主的扑克游戏.斗地主是一种使用黑桃.红心.梅花.方片的A到K加上大小王的共54张牌来进行的扑克牌游戏.在斗地主中,牌的大小关系根据牌的数码表示如下:3<4< ...
- 如何用css3实现一个图片的抖动或者弹跳
<li onmouseout="this.className='off'"><a href=""><img src=". ...
- 中介者模式(Mediator Pattern)
定义一个中介对象来封装系列对象之间的交互.中介者使各个对象不需要显示地相互引用,从而使其耦合性松散,而且可以独立地改变他们之间的交互. Mediator:中介者接口.在里面定义了各个同事之间相互交互所 ...
- 创建支持ssh服务的docker容器和镜像
http://www.kongxx.info/blog/?p=57 1. 这里使用的centos作为容器,所以首先下载centos的imagessudo docker pull centos 2. 下 ...