Tomcat源码解析:2、Tomcat结构组成

在看源码之前,我们首先得了解Tomcat的结构组成,并且了解它每个组件的作用,这样我们看才不会一脸懵逼。

总体结构

tomcat的总体架构如下图所示(摘自https://blog.csdn.net/Dwade_mia/article/details/79051404)
Tomcat源码解析:2、Tomcat结构组成_第1张图片

如上图所示:Tomcat由Server、Service、Engine、Connector、Host、Context、Wrapper组成,图中由括号有s的组件,代表在Tomcat实例中可以出现多个。

组件作用

1、Server:由1-n个Service组成,让其他程序可以访问Service集合,提供对Service集合的管理【增删改查】。还提供Tomcat初始化、Tomcat关闭等功能

2、Service:它由单个Container【一般是Engine】、多个Connector组成。只是在Container和Connector外,多包了一层,提供对这几个组件的管理。还有提供一个桥梁,让Connector可以访问Container。

3、Connector:负责接收TCP连接请求,创建Request/Response,分配请求处理线程,将创建的对象交给Container处理。(Connector通过Service可以获取到Container)

4、Container是容器的父接口,由四个容器组成,分别是Engine,Host,Context,Wrapper。其中Engine包含Host,Host包含Context,Content包含Wrapper,一个Servlet class对应一个Wrapper。

5、Engine:Container的顶级组件。有了Engine,请求的处理过程就变成,Connector接收请求,将请求交给Engine,Engine找到对应的Host,Host拿到请求后查找对应的项目【也就是Context】,Context根据对应的Url找到对应的Wrapper【也就是Servlet】,最后Servlet对请求做出相应的处理

6、Host:顾名思义:虚拟主机,提供一台主机,有多个域名可以访问,当然默认是localhost,配置了Host域名,也要在hosts文件添加映射,要不不起作用。它还有提供自动解压War包、指定部署路径【也就是说:项目部署不一定要防在webapps下,可以自定义配置】等功能

7、Context:对应一个Web项目,也可以理解为多个Servlet的集合。譬如说webapps下有两个项目,那么则有2个Context组件。每个Context的Servlet集合是分开的,它的功能主要是对Servlet的管理、Session管理等功能。

8、Wrapper:它就是我们平时使用的Servlet了。它负责Servlet生命管理、初始化、执行、资源回收等

像上面的组件都可以在server.xml中,可以找到对应的标签【标签对应中组件,可以这样理解】

<?xml version="1.0" encoding="UTF-8"?>

<Server port="8005" shutdown="SHUTDOWN">
  <Listener className="org.apache.catalina.startup.VersionLoggerListener" />
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />


  <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>

  <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">
      <Realm className="org.apache.catalina.realm.LockOutRealm">
        <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
               resourceName="UserDatabase"/>
      </Realm>

      <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 "%r" %s %b" />
      </Host>
    </Engine>
  </Service>
</Server>

组件的代码介绍

Server

Server:org.apache.catalina.Server
它的实现类是:org.apache.catalina.core.StandardServer

public interface Server extends Lifecycle {

    public NamingResourcesImpl getGlobalNamingResources();

    public void setGlobalNamingResources(NamingResourcesImpl globalNamingResources);

    public javax.naming.Context getGlobalNamingContext();

    public int getPort();

    public void setPort(int port);

    public String getAddress();

    public void setAddress(String address);

    public String getShutdown();

    public void setShutdown(String shutdown);

    public ClassLoader getParentClassLoader();

    public void setParentClassLoader(ClassLoader parent);

    public Catalina getCatalina();

    public void setCatalina(Catalina catalina);

    public File getCatalinaBase();

    public void setCatalinaBase(File catalinaBase);

    public File getCatalinaHome();

    public void setCatalinaHome(File catalinaHome);

    public void await();

    public Service findService(String name);

    public Service[] findServices();

    public void removeService(Service service);

    public Object getNamingToken();
}

由上面可知,Server继承Lifecycle类【上面所有的组件,都是直接继承Lifecycle类或者间接继承Lifecycle类】;Lifecycle类它是非常重要的一个接口,用于管理Tomcat的生命中期,例如init、start、stop、destory;另外它使用了观察者模式,Lifecycle是一个监听者,它会向注册到的LifecycleListener观察者发出各种事件,后面会抽出一节来讲。

Server提供了对Service管理、包括getCatalina、getCatalinaHome等功能

Service

Service:org.apache.catalina.Service
它的实现类为:org.apache.catalina.core.StandardService

public interface Service extends Lifecycle {

    public Engine getContainer();

    public void setContainer(Engine engine);

    public String getName();

    public void setName(String name);

    public Server getServer();

    public void setServer(Server server);

    public ClassLoader getParentClassLoader();

    public void setParentClassLoader(ClassLoader parent);

    public String getDomain();

    public void addConnector(Connector connector);

    public Connector[] findConnectors();

    public void removeConnector(Connector connector);

    public void addExecutor(Executor ex);

    public Executor[] findExecutors();

    public Executor getExecutor(String name);

    public void removeExecutor(Executor ex);

    Mapper getMapper();
}

由上面可知,它具有以下功能

  1. 持有Server实例。这是Tomcat组件的一个特点,父组件提供对子组件的管理,但是子组件一般也持有父组件的实例
  2. 持有Engine实例,也就上面的Container
  3. 持有Executor实例
  4. 可以管理多个Connector实例
  5. 继承至Lifecycle

Connector

由Tomcat的server.xml配置文件可知默认会初始化两个Connector,一个是负责Http请求的Connector,一个是负责AJP请求的Connector

	<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" />
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

Container

Container:org.apache.catalina.Container
它对应的四种不同的组件:

  1. Engine:表示整个Catalina的servlet引擎
  2. Host:虚拟主机,拥有若干个Context
  3. Context:表示一个Web项目,一个Context拥有多个Wrapper
  4. Wrapper:表示一个独立的Servlet

Engine、Host、Context、Wrapper都有一个默认的实现类StandardXXX,均继承至ContainerBase,提供了一些常用的Container接口的实现。

public abstract class ContainerBase extends LifecycleMBeanBase
        implements Container {
        ```省略
}

一个容器可以有一个或多个低层次的子容器,并且一个Catalina功能部署并不一定需要全部四种容器。一个Context有一个或多个wrapper,而wrapper作为容器层次中的最底层,不能包含子容器。从一个容器添加到另一容器中可以使用在Container接口中定义的addChild()方法:

public void addChild(Container child); 

删除一个容器可以使用Container接口中定义的removeChild()方法:

public void removeChild(Container child); 

另外容器接口支持子接口查找和获得所有子接口集合的方法findChild和findChildren方法:

public Container findChild(String name); 
public Container[] findChildren(); 

Engine

Engine:org.apache.catalina.Engine
它的实现类是:org.apache.catalina.core.StandardEngine

public interface Engine extends Container {

    public String getDefaultHost();

    public void setDefaultHost(String defaultHost);

    public String getJvmRoute();

    public void setJvmRoute(String jvmRouteId);

    public Service getService();

    public void setService(Service service);
}

对应server.xml

<Engine name="Catalina" defaultHost="localhost">
	```省略
</Engine>

由上面可知:

  1. 它持有Service的实例
  2. 它继承Contanier接口

Host

Host:它表示一个虚拟主机。正所谓虚拟主机,当然是可以用来部署应用程序的,Tomcat的Host也是如此。它在server.xml中定义了一个localhost的Host,应用根目录在webapps下面,默认是支持解压重新部署的

<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"/>

name:虚拟主机名
appBase:部署目录,也叫根目录
unpackWAR:true,自动解压war包,false,反之
autoDeploy:true,自动部署,false,反之

Context

Context:一个独立的web应用,每个Context,tomcat都是使用不同的Classloader避免类冲突。如果我们希望使用一个自定义的目录作为部署路径的话,可以在server.xml中新增Context即可

<Context path="/static" docBase="D:/static" reloadable="true"></Context>

你可能感兴趣的:(Tomcat源码解析,Tomcat)