Tomcat简单分析-Container

1.Container的有四个子容器,分别是Engine,Host,Context,Wrapper,如下:


2.Container一个也有四个子接口Engine,Host,Context,Wrapper和一个默认实现类ContainerBase,另外这四个子容器都是对应一个StandardXXX实现类,都继承ContainerBase,并且Container还继承LifeCycle接口,所以这四个容器也是符合Tomcat的生命周期模式,结构图如下:

    

3.解析四个子容器

    3.1 Engine:引擎,分别用来管理多个站点,一个Service最多只能有一个Engine

    3.2 Host:表示一个站点,通过配置Host可以添加站点

    3.3 Context:表示一个应用程序,对应着平时开发对应的一套程序,或者一个WEB-INF目录以及下面的web.xml文件

    3.4 Wrapper:每个Wrapper封装一个Servlet

理解Host和Context区别看图:

        

  3.5 四种容器的配置方法

    3.5.1 Engine和Host的配置都在conf/server.xml中,默认的server.xml配置文件如下:

 <Server port="8005" shutdown="SHUTDOWN">  <!--8005端口监听关闭名利SHUTDOWN-->
  <Listener className="org.apache.catalina.startup.VersionLoggerListener"/>

  <Listener SSLEngine="on" className="org.apache.catalina.core.AprLifecycleListener"/>

  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener"/>
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener"/>
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener"/>


  <GlobalNamingResources>
  
    <Resource auth="Container" description="User database that can be updated and saved" factory="org.apache.catalina.users.MemoryUserDatabaseFactory" name="UserDatabase" pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>
  </GlobalNamingResources>


  <Service name="Catalina">  <!--Service服务名Catalina-->
        <!--Http协议的connector-->
    <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>
        <!--AJP协议的端口-->
    <Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/>
        <!--默认的Host即localhost-->
    <Engine defaultHost="localhost" name="Catalina">

      <Realm className="org.apache.catalina.realm.LockOutRealm">

        <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
      </Realm>
        <!--appBase就是我们定义的站点webapps,autoDeploy 为true表示自动部署,unpachWAR为true表示自动解压WAR文件-->
      <Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true">
        <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" pattern="%h %l %u %t "%r" %s %b" prefix="localhost_access_log" suffix=".txt"/>
        <!--这是我自己的一个Metting项目-->
      <Context docBase="E:\apache-tomcat-9.0.4\webapps\Metting-Web" path="/Metting-Web" reloadable="true" source="org.eclipse.jst.jee.server:Metting-Web"/></Host>
    </Engine>
  </Service>
</Server>

另外Host还有一个Alias子标签,可以通过域名访问同一个站点可以这样定义,比如www.visonws.com和visonws.com访问同意站点可以:

<Host name="www.visonws.com" appBase="/webapps" unpackWARS="true" autoDeploy="true">

    <Alias>visonws.com</Alias>

</Host>

Engine在定义的时候有一个defaultHost属性,他表示如果在Host的name和Alias都找不到时就是用默认的Host.

    3.5.2 Context有三种配置,

        I:通过文件配置,

        II:将WAR应用直接放到Host目录下去,Tomcat会自动查找并添加到Host中 

        III:将应用的文件夹放到Host目录下,Tomcat也会自动查找添加到Host中

    通过文件配置有五个地方配置:

        1>:conf/server.xml文件的Context标签

        2>:conf/[enginename]/[hostname]/目录下以应用命名的xml文件

        3>:应用自己的/META-INF/context.xml文件

        前三个用于配置单独的应用,另外conf/server.xml只有在Tomcat重启时候重新加载

        4>:conf/context.xml文件 ,这个是在Tomcat中共享

        5>::conf/[enginename]/[hostname]/context.xml.default文件,这个实在对应的站点共享

    3.5.3 Wrapper的配置就是我们再web.xml中的配置Servlet,一个Servlet对应一个Wrapper,另外也可以在conf/web.xml文件配置全局的Wrapper,处理Jsp的JspServlet就是配置在这里,所以不用自己配置JspServlet就可以处理Jsp请求了。

4. Container的启动

        4.1 ContainerBase,  四个容器有一个共同的父类ContainerBase,这个父类包含initInternal和startInternal方法。

        initInternal方法用来初始化ThreadPoolExecutor类型的startStopExecutor属性,用于启动和关闭线程。

        startInternal方法主要做了五件事:

            1>:如果有Cluster和Realm则调用了start方法(Cluster用于配置集群,他的作用是同步Session,Realm是Tomcat的安全域,可以 用来管理资源的访问权限,server.xml中有注释的参考配置)

            2>:调用所有子容器的start方法启动子容器,子容器Future是阻塞的,所以只有在子容器全部启动完了,才启动管道Valve

            3>:调用管道中Valve的start方法启动管道

            4>:启动完成后将生命周期状态设置为LifeCycleState.STARTING

            5>:启动后台程序定时处理一些事情,后台线程是一个while循环,内部会定期调用 backgroundProcess做一些事情。

    backgroundProcess方法在Container接口中有一个方法,一共有三个实现,分别在ContainerBase,StandardContext和StandardWrapper中,

    ContainerBase提供了所有容器共同的处理过程。

    StandardContext的backgroundProcess除了处理自己的相关业务,还对Session过期和资源变化进行了处理

    StandardWrapper的backgroundProcess除了处理自己的相关业务,会对Jsp生成的Servlet定期进行检查

     4.2 Engine  他的默认实现类是StandardEngine,它里面的方法有initInternal和startInternal

     4.3 Host 默认实现类StandardHost,初始化默认调用ContainerBase的initInternal方法,有startInternal方法,还有HostConfig方法,可以简单地做日志记录,HostConfig中的start方法会检查配置的Host站点配置的位置是否存在以及是不是目录,最后调用deployApps方法部署应用,有三种方式部署,XML描述文件,WAR文件和文件夹部署。

看源代码:

protected void deployApps(String name) {
        File appBase = this.host.getAppBaseFile();
        File configBase = this.host.getConfigBaseFile();
        ContextName cn = new ContextName(name, false);
        String baseName = cn.getBaseName();
        if (!this.deploymentExists(cn.getName())) {
            File xml = new File(configBase, baseName + ".xml");
            if (xml.exists()) {    
                this.deployDescriptor(cn, xml);
            } else {
                File war = new File(appBase, baseName + ".war");
                if (war.exists()) {
                    this.deployWAR(cn, war);
                } else {
                    File dir = new File(appBase, baseName);
                    if (dir.exists()) {
                        this.deployDirectory(cn, dir);
                    }

                }
            }
        }
    }

     4.4 Context 他的默认实现类是StandardContext在startInternal中调用了web.xml中的Listener,另外还初始化了启动的Filter和load-on-startup的Servlet.  Context和Host一样也有一个LifecycleLIstener类型的监听器ContextConfig,configureStart防范用来处理CONFIGURE_START_EVENT事件,这个方法调用webConfig方法,webConfig解析web.xml文件,相应的创建了Wrapper并使用gaddChild添加到了Context里面。

     4.5 Wrapper 他的默认实现类是StandardWrapper,初始化默认调用ContainerBase的initInternal方法,有自己的startInternal方法。

            

猜你喜欢

转载自blog.csdn.net/weixin_40792878/article/details/80933239