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的启动。。。

时间: 2024-10-08 17:51:22

tomcat源码剖析的相关文章

tomcat(12)org.apache.catalina.core.StandardContext源码剖析

[0]README 0)本文部分文字描述转自 "how tomcat works",旨在学习 "tomcat(12)StandardContext源码剖析" 的基础知识: 1)Context实例表示一个具体的web 应用程序,其中包含一个或多个Wrapper实例,每个Wrapper 表示一个具体的servlet定义: 2)Context容器还需要其他组件的支持,如载入器和Session 管理器.本章要intro 的 StandardContext是 catalina

tomcat(11)org.apache.catalina.core.StandardWrapper源码剖析

[0]README 0.0)本文部分文字描述转自 "how tomcat works",旨在学习 "tomcat(11)StandardWrapper源码剖析" 的基础知识: 0.1)StandardWrapper 是 Catalina中对Wrapper接口的标准实现:要知道,tomcat 中有4种类型的容器:Engine,Host,Context 和 Wrapper:(干货--review  tomcat 中有4种类型的容器:Engine,Host,Context

75篇关于Tomcat源码和机制的文章

75篇关于Tomcat源码和机制的文章 标签: tomcat源码机制 2016-12-30 16:00 10083人阅读 评论(1) 收藏 举报  分类: tomcat内核(82)  版权声明:本文为博主原创文章,未经博主允许不得转载. 整理下前面写过的75篇关于Tomcat源码和机制的文章 文章列表 如何设计一个Web容器 Web安全认证机制知多少 Tomcat集群实现源码级别剖析 Tomcat集群如何同步会话 从单机到集群会话的管理之集群模式一 从单机到集群会话的管理之集群模式二(更大的集群

jetty源码剖析

最近使用jetty自己写了一个web server,现在闲了花了一天的时间看了一jetty的源代码,主要以server的启动为主线,进行了剖析,经过阅读对jetty的源码大赞,写的简洁.清晰,架构也不复杂,好多东西值得借鉴.具体代码级别的剖析也不便在这贴了,提供一篇在阅读源码时的预备文章,见下面网址. jetty的工作原理以及与tomcat的比较:http://www.ibm.com/developerworks/cn/java/j-lo-jetty/ jetty源码剖析,布布扣,bubuko.

Tomcat源码分析——请求原理分析(下)

前言 本文继续讲解TOMCAT的请求原理分析,建议朋友们阅读本文时首先阅读过<TOMCAT源码分析——请求原理分析(上)>和<TOMCAT源码分析——请求原理分析(中)>.在<TOMCAT源码分析——请求原理分析(中)>一文我简单讲到了Pipeline,但并未完全展开,本文将从Pipeline开始讲解请求原理的剩余内容. 管道 在Tomcat中管道Pipeline是一个接口,定义了使得一组阀门Valve按照顺序执行的规范,Pipeline中定义的接口如下: getBas

Tomcat源码分析——启动与停止服务

前言 熟悉Tomcat的工程师们,肯定都知道Tomcat是如何启动与停止的.对于startup.sh.startup.bat.shutdown.sh.shutdown.bat等脚本或者批处理命令,大家一定知道改如何使用它,但是它们究竟是如何实现的,尤其是shutdown.sh脚本(或者shutdown.bat)究竟是如何和Tomcat进程通信的呢?本文将通过对Tomcat7.0的源码阅读,深入剖析这一过程. 由于在生产环境中,Tomcat一般部署在Linux系统下,所以本文将以startup.s

Tomcat源码分析--转

一.架构 下面谈谈我对Tomcat架构的理解 总体架构: 1.面向组件架构 2.基于JMX 3.事件侦听 1)面向组件架构 tomcat代码看似很庞大,但从结构上看却很清晰和简单,它主要由一堆组件组成,如Server.Service.Connector等,并基于JMX管理这些组件,另外实现以上接口的组件也实现了代表生存期的接口Lifecycle,使其组件履行固定的生存期,在其整个生存期的过程中通过事件侦听LifecycleEvent实现扩展.Tomcat的核心类图如下所示: 1.Catalina

下载-深入浅出Netty源码剖析、Netty实战高性能分布式RPC、NIO+Netty5各种RPC架构实战演练三部曲视频教程

下载-深入浅出Netty源码剖析.Netty实战高性能分布式RPC.NIO+Netty5各种RPC架构实战演练三部曲视频教程 第一部分:入浅出Netty源码剖析 第二部分:Netty实战高性能分布式RPC 第三部分:NIO+Netty5各种RPC架构实战演练

Phaser实现源码剖析

在这里首先说明一下,由于Phaser在4.3代码里是存在,但并没有被开放出来供使用,但已经被本人大致研究了,因此也一并进行剖析. Phaser是一个可以重复利用的同步栅栏,功能上与CyclicBarrier和CountDownLatch相似,不过提供更加灵活的用法.也就是说,Phaser的同步模型与它们差不多.一般运用的场景是一组线程希望同时到达某个执行点后(先到达的会被阻塞),执行一个指定任务,然后这些线程才被唤醒继续执行其它任务. Phaser一般是定义一个parties数(parties一