天天看点

Tomcat源码分析(二):配置文件server.xml解读

前言

tomcat源码都是围绕着server.xml这个配置文件展开来看的,所以我们分析它的源码也需要从它开始入手。

概览

Tomcat的组织结构很简单,下面一张图能够清晰的展示出来。

Tomcat源码分析(二):配置文件server.xml解读

Server是Tomcat中最顶层的容器,代表着整个服务器,一个Server可以包含至少一个Service,用于具体提供服务。

Service主要包含两个核心组件:Connector和Container。

Connector组件负责处理请求监听,一个Connector与一个TCP端口绑定,接受Socket请求并将请求封装成Request和Response

Container组件负责处理请求处理,用于封装和管理Servlet,以及具体处理Request请求

至于具体的请求,我们通过源码说明。

配置文件源码分析

每个组件都能够在源码中体现出来,这里我提供一份自己添加了注释的配置文件,可以参照理解。

并且我会在下面对核心组件进行具体分析。

<?xml version='1.0' encoding='utf-8'?>

<!--
Server是一个顶级组件,代表了一个Tomcat实例,一个JVM进程中只能有一个Server实例。
Tomcat提供了一个实现了 org.apache.catalina.Server接口的 org.apache.catalina.core.StandardServer默认类,读取Server元素配置。

Server是配置文件中的最外层元素,支持以下属性:
      className:指定要使用的实现类(必须实现org.apache.catalina.Server接口)名称。如果不指定,默认使用标准实现类StandardServer。
      address:等待shutdown命令的服务器IP地址,默认是localhost。
      port:等待shutdown命令的监听端口,如果设置为-1,表示关闭shutdown端口。
      shutdown:指定终止Tomcat服务器运行时,发给Tomcat服务器的shutdown监听端口的字符串.该属性必须设置 。
-->
<Server port="8015" shutdown="SHUTDOWN">
    <Listener className="org.apache.catalina.startup.VersionLoggerListener"/>
    <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on"/>
    <Listener className="org.apache.catalina.core.JasperListener"/>
    <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
    <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
    <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener"/>

    <!--定义的全局JNDI资源-->
    <GlobalNamingResources>
        <Resource name="UserDatabase" auth="Container"
                  type="org.apache.catalina.UserDatabase"
                  description="User database that can be updated and saved"
                  factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
                  pathname="conf/tomcat-users.xml"/>
    </GlobalNamingResources>

    <!--Server元素中可以有一个或多个Service,每个Service关联了多个Connector和一个Engine。
    Service支持两个属性:
        className:指定要使用的实现类(必须实现org.apache.catalina.Service接口)名称。如果不指定,默认使用标准实现类StandardService。
        name:Service的名称,在同一个Server元素中必须唯一,默认是Catalina。
    -->
    <Service name="Catalina">

        <!--Connector负责处理请求监听,一个Connector与一个TCP端口绑定,接受请求并将请求封装成Request和Response,Service中默认包含两个Connector。
            Connector支持四个属性:
                port:属性指定监听端口,默认8080端口,可修改为1024-65535间的任意一个端口
                protocol:支持协议
                connectionTimeout:定义连接器等待时间,默认20秒
                redirectPort:SSL请求会重定向到8443端口
        -->
        <!--HTTP/1.1:处理HTTP请求,此连接器使Tomcat可以作为HTTP服务器使用。-->
        <Connector port="8090" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8453"/>
        <!--AJP/1.3:Apache JServ 协议处理Tomcat与Apache之间的通信。Tomcat核心功能是解析Servlet,html和图片解析功能相对其他HTTP服务器较弱(如Apache HTTP Server),所以,一般都是集成使用,Apache处理静态页面请求,Tomcat处理Servlet/JSP请求。-->
        <Connector port="8019" protocol="AJP/1.3" redirectPort="8453"/>

        <!--Container负责处理请求处理,有四个子容器:Engine、Host、Context和Wrapper,他们之间是父子包含关系。-->
        <!--一个Service只有一个Engine,表示整个Servlet引擎,其主要作用是执行业务逻辑;从HTTP Connector接收HTTP请求,并且会根据主机名/IP地址交由相应的主机处理请求。-->
        <Engine name="Catalina" defaultHost="localhost">
            <Realm className="org.apache.catalina.realm.LockOutRealm">
                <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
            </Realm>

            <!--Host,代表一个站点,也可以叫虚拟主机,一个Engine下面可以包含一个或者多个Host,即一个Tomcat实例可以配置多个虚拟主机-->
                <!--appBase:定义了应用程序的根目录,默认是webapps-->
                <!--unpackWARS:定义了是否解压webapps中的WAR文件,如果指定为“false”,会从WAR文件直接运行程序,执行较慢-->
                <!--autoDeploy:把应用程序直接拖到webapps目录下,是否自动运行-->
            <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
                <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="localhost_access_log." suffix=".txt" pattern="%h %l %u %t &quot;%r&quot; %s %b"/>
                <!--
                Context,代表一个应用程序
                    path:访问项目时的URL,加在localhost:8080后
                    docBase:path对应的项目目录
                    reloadable:监视 /WEB-INF/classes/ 和 /WEB-INF/lib目录中的类文件,更改后自动重载应用程序,
                    生成环境不建议使用,默认为“false”
                -->
                <Context path="/image" docBase="/opt/file/img" reloadable="false"></Context>
                <!--Wrapper针对的是每个具体的servlet-->
            </Host>
        </Engine>
    </Service>
</Server>

           

tomcat的核心组件

介绍下tomcat的核心组件Connector组件和Container组件

Connector组件

Connector组件负责处理请求监听,一个Connector与一个TCP端口绑定,接受Socket请求并将请求封装成Request和Response对象,然后将产生的 Request 和 Response 对象传给处理Engine(Container中的一部分),真正处理请求的是Engine。

Tomcat源码分析(二):配置文件server.xml解读

Service中默认包含两个Connector,HTTP协议和AJP协议,HTTP协议接收http请求,使Tomcat可以作为HTTP服务器使用。AJP协议处理Tomcat和Apache服务器之间的请求。

Connector在Tomcat中的设计如图所示。这里不深入讨论,后续再深入。

Tomcat源码分析(二):配置文件server.xml解读

Container组件

Container负责处理请求处理,Container是容器的父接口,有四个子容器:Engine、Host、Context和Wrapper,他们之间是父子包含关系。体系结构如下:

Tomcat源码分析(二):配置文件server.xml解读
  • Engine 容器

    一个Service只有一个Engine,表示整个Servlet引擎,其主要作用是执行业务逻辑;从HTTP Connector接收HTTP请求,并且会根据主机名/IP地址交由相应的主机处理请求。uml类图如下

    Tomcat源码分析(二):配置文件server.xml解读
  • Host 容器

    代表一个站点,也可以叫虚拟主机,一个Engine下面可以包含一个或者多个Host,即一个Tomcat实例可以配置多个虚拟主机,uml类图如下。

    Tomcat源码分析(二):配置文件server.xml解读
  • Context 容器

    Context 代表 Servlet 的 Context,它具备了 Servlet 运行的基本环境,理论上只要有 Context 就能运行 Servlet 了。简单的 Tomcat 可以没有 Engine 和 Host。Context 最重要的功能就是管理它里面的 Servlet 实例,Servlet 实例在 Context 中是以 Wrapper 出现的,uml类图如下。

    Tomcat源码分析(二):配置文件server.xml解读
  • Wrapper 容器

    Wrapper 代表一个 Servlet,它负责管理一个 Servlet,包括的 Servlet 的装载、初始化、执行以及资源回收。Wrapper 是最底层的容器,它没有子容器了,所以调用它的 addChild 将会报错。

    Wrapper 的实现类是 StandardWrapper,StandardWrapper 还实现了拥有一个 Servlet 初始化信息的 ServletConfig,由此看出 StandardWrapper 将直接和 Servlet 的各种信息打交道。uml类图如下。

    Tomcat源码分析(二):配置文件server.xml解读

tomcat其他组件

Tomcat 还有其它重要的组件,如安全组件 security、logger 日志组件、session、mbeans、naming 等其它组件。这些组件共同为 Connector 和 Container 提供必要的服务。

小结

现在我们了解了,tomcat的整体结构大概是这个样子。

Tomcat源码分析(二):配置文件server.xml解读

整个启动流程也是很标准化的,入口是BootStrap,统一按照生命周期管理接口Lifecycle的定义进行启动。首先,调用init()方法逐级初始化,接着调用start()方法进行启动,同时,每次调用伴随着生命周期状态变更事件的触发。

每一级组件除完成自身的处理外,还有负责调用子组件的相关调用,组件和组件之间是松耦合的,可以通过配置进行修改。

Tomcat源码分析(二):配置文件server.xml解读

学习tomcat的源码,参考了https://blog.csdn.net/w1992wishes/article/details/79242797这篇文章,感觉写的不错,可以参考下。