Tomcat

Tomcat是Apache基金会的开源软件。Tomcat实现了Jakarta Servlet,Jakarta Server Pages,Jakarta Websocket,Jakarta Annotations以及 Jakarta Authentication 等规范;是一个Servlet容器,也就是说Tomcat是实现了部分J2EE规范的服务器。

Tomcat9之前都是使用的J2EE,而在Tomcat10之后全部使用JakartaEE规范。

官方网站:https://tomcat.apache.org

源代码:https://github.com/apache/tomcat

如何阅读源码

  1. 查看README,准备官方文档

  2. 分析项目结构

  3. 分析配置文件

  4. 不要使用调试递进的形式进行源码研究。而是一定要利用自己的语言知识,来进行推理和阅读

  5. 看接口划分模块

  6. 模块划分之后,逐个击破,广度优先,而非深度优先,不要深究模块之间的联系

  7. 融会贯通(研究细节)

tomcat的项目结构以及目录

源码路径:

/bin        二进制,大部分是执行脚本,分为linux以及windows
/conf       配置文件夹
/logs       日志路径
/res        tomcat的一些资源,比如欢迎页面
/webapps    存放servlet的文件夹,默认会有管理页等
/work       工作路径,比如jsp解析完成后的servlet java文件

环境变量:

CATALINA_HOME: CATALINA是Tomcat的心脏,也就是tomcat的核心引擎,该变量表示tomcat应用程序的家目录
CATALINA_BASE: 代表tomcat运行实例的目录,一台机器中可能运行多个tomcat实例,默认在tomcat的安装目录下

根据 catalina.sh start 可以最终找到启动类:org.apache.catalina.startup.Bootstrap

配置文件

server.xml

tomcat启动的最核心的配置文件,结构如下:

<Server port="8005" shutdown="SHUTDOWN">
    <Service name="Catalina">
        <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
        <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
        <Engine name="Catalina" defaultHost="localhost">
            <Host name="localhost"  appBase="webapps" unpackWARs="true" autoDeploy="true">
                <Context />
                <Context /> <!--代表一个web应用程序-->
            </Host>
        </Engine>
    </Service>
    <Service>...</Service>
</Server>
  1. Server 元素代表tomcat服务实例,其中端口8005用于关闭服务的监听端口

  2. Service 元素则代表一个Engine元素以及一组与之相连的Connector元素,可以有多个Service,多个Service之间的Connnector是相互隔离的。

  3. Connector 元素是用于与客户端建立连接请求的连接器,可指定连接的端口、协议、连接超时时间等

  4. Engine 元素是用于处理连接请求并返回响应结果的引擎,一个Engine包含多个host

  5. Host 元素处理一个特定的host主机,一个host又有可能包含多个不同的web应用程序

  6. Context 代表一个应用程序,一个web应用程序中又包含多个Servlet

web.xml

web.xml是Tomcat的所有的web应用的属性默认值。

logging.properties

日志配置,包含日志级别,打印格式等。

context.xml

context代表了一个web应用程序,该配置主要监听 WEB-INF下的资源,当这些资源发生变动时,立马重新加载应用。

<Context>
    <WatchedResource>WEB-INF/web.xml</WatchedResource>
    <WatchedResource>${catalina.base}/conf/web.xml</WatchedResource>
</Context>

Tomcat架构

Tomcat的整体架构是一个树形结构,每个组件负责管理自己的生命周期以及他的子组件的生命周期。

通过对该组件树进行前序遍历,可以很方便的控制父组件与其下的子组件的生命周期状态。比如要将server状态变为start,将会使用前序遍历的方式依次寻找service、connector、engine、host、context组件,当所有子组件启动后,server就完成了启动。并且,可以在这些步骤中增加Listener以监听每个组件的状态变化。

组件的生命周期管理

每个组件都实现Lifecycle接口,此接口定义了组件的主要的生命周期方法,他的定义如下,在该接口的注释中,明确定义了整个生命周期的状态机图,以及事件监听的相关方法:

/**
 *            start()
 *  -----------------------------
 *  |                           |
 *  | init()                    |
 * NEW -»-- INITIALIZING        |
 * | |           |              |     ------------------«-----------------------
 * | |           |auto          |     |                                        |
 * | |          \|/    start() \|/   \|/     auto          auto         stop() |
 * | |      INITIALIZED --»-- STARTING_PREP --»- STARTING --»- STARTED --»---  |
 * | |         |                                                            |  |
 * | |destroy()|                                                            |  |
 * | --»-----«--    ------------------------«--------------------------------  ^
 * |     |          |                                                          |
 * |     |         \|/          auto                 auto              start() |
 * |     |     STOPPING_PREP ----»---- STOPPING ------»----- STOPPED -----»-----
 * |    \|/                               ^                     |  ^
 * |     |               stop()           |                     |  |
 * |     |       --------------------------                     |  |
 * |     |       |                                              |  |
 * |     |       |    destroy()                       destroy() |  |
 * |     |    FAILED ----»------ DESTROYING ---«-----------------  |
 * |     |                        ^     |                          |
 * |     |     destroy()          |     |auto                      |
 * |     --------»-----------------    \|/                         |
 * |                                 DESTROYED                     |
 * |                                                               |
 * |                            stop()                             |
 * ----»-----------------------------»------------------------------
 * 
 * 任何一个状态都可以变为 FAILD
 */
public interface Lifecycle {

    // 生命周期事件
    public static final String BEFORE_INIT_EVENT = "before_init";
    public static final String AFTER_INIT_EVENT = "after_init";
    public static final String START_EVENT = "start";
    public static final String BEFORE_START_EVENT = "before_start";
    public static final String AFTER_START_EVENT = "after_start";
    public static final String STOP_EVENT = "stop";
    public static final String BEFORE_STOP_EVENT = "before_stop";
    public static final String AFTER_STOP_EVENT = "after_stop";
    public static final String AFTER_DESTROY_EVENT = "after_destroy";
    public static final String BEFORE_DESTROY_EVENT = "before_destroy";
    // 周期性事件,后台线程定时执行一些事情,比如热部署、热替换
    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 void addLifecycleListener(LifecycleListener listener);
    public LifecycleListener[] findLifecycleListeners();
    public void removeLifecycleListener(LifecycleListener listener);

    // 生命周期方法
    public void init() throws LifecycleException;
    public void start() throws LifecycleException;
    public void stop() throws LifecycleException;
    public void destroy() throws LifecycleException;

    // 获取当前生命周期状态
    public LifecycleState getState();
    // 获取状态名称
    public String getStateName();
    
    // 标记接口,标记组件只使用一次
    public interface SingleUse {
    }
}

生命周期监听器:

public interface LifecycleListener {
    // 接收事件对象,并处理事件
    public void lifecycleEvent(LifecycleEvent event);
}

事件接口:

import java.util.EventObject;

public final class LifecycleEvent extends EventObject {

    private static final long serialVersionUID = 1L;

    public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {
        super(lifecycle);
        this.type = type;
        this.data = data;
    }
    // 事件传递的数据
    private final Object data;
    // 事件的类型
    private final String type;

    public Object getData() {
        return data;
    }

    // 事件所发生的目标生命周期
    public Lifecycle getLifecycle() {
        return (Lifecycle) getSource();
    }

    public String getType() {
        return this.type;
    }
}

组件的生命周期状态枚举:

public enum LifecycleState {
    NEW(false, null),

    INITIALIZING(false, Lifecycle.BEFORE_INIT_EVENT),
    INITIALIZED(false, Lifecycle.AFTER_INIT_EVENT),
    STARTING_PREP(false, Lifecycle.BEFORE_START_EVENT),

    STARTING(true, Lifecycle.START_EVENT),
    STARTED(true, Lifecycle.AFTER_START_EVENT),
    STOPPING_PREP(true, Lifecycle.BEFORE_STOP_EVENT),
    
    STOPPING(false, Lifecycle.STOP_EVENT),
    STOPPED(false, Lifecycle.AFTER_STOP_EVENT),
    DESTROYING(false, Lifecycle.BEFORE_DESTROY_EVENT),
    DESTROYED(false, Lifecycle.AFTER_DESTROY_EVENT),
    
    FAILED(false, null);

    // 组件是否可用
    private final boolean available;
    // 生命周期事件
    private final String lifecycleEvent;

    private LifecycleState(boolean available, String lifecycleEvent) {
        this.available = available;
        this.lifecycleEvent = lifecycleEvent;
    }

    public boolean isAvailable() {
        return available;
    }

    public String getLifecycleEvent() {
        return lifecycleEvent;
    }
}

最后更新于