Tomcat的核心组件以及server.xml配置全解【一万字】

详细介绍了Tomcat的核心组件以及server.xml配置全解,以及请求处理流程。

前面我们简单介绍了Tomcat服务器的基本概念,现在我们来简单看看它的核心配置文件server.xml。

本文将会介绍Tomcat中比较重要的一些配置和概念,而又不会太深入底层,本文并不是专业的Tomcat学习文章。如果你是Java学习者或者开发者,并且没有专门的时间和计划去详细学习Tomcat服务器,那么本文值得一看!

文章目录

  • 1 server.xml文件概述
  • 2 Server
  • 2 Listener
  • 3 GlobalNamingResources
    • 3.1 Environment
    • 3.2 Resource
      • 3.2.1 manager
  • 4 Service
  • 5 Executor
  • 6 Connector
  • 7 Engine
  • 8 Host
    • 8.1 Context
    • 8.2 Web应用的自动部署
    • 8.3 自动部署与Context
    • 8.4 静态部署Web应用
  • 9 tomcat的请求查找流程
    • 9.1 根据协议和端口号选定Service和Engine
    • 9.2 根据域名或IP地址选定Host
    • 9.3 根据URI选定Context(Web应用)

1 server.xml文件概述

tomcat是组件式架构,它的server.xml配置文件中可以通过标签配置tomcat容器中的不同类型的组件,是tomcat的核心配置文件。

server.xml中的主要组件(标签)的关系如下(并没有展示全部组件的关系):

Tomcat的核心组件以及server.xml配置全解【一万字】_第1张图片

Server标签在最顶层,代表整个Tomcat容器;一个Server元素中可以有一个或多个Service元素。

Service在Connector和Engine外面包了一层,把它们组装在一起,对外提供服务。一个Service可以包含多个Connector,但是只能包含一个Engine;Connector接收请求,Engine处理请求。

Engine、Host和Context都是容器,且 Engine包含Host,Host包含Context。每个Host组件代表Engine中的一个虚拟主机;每个Context组件代表在特定Host上运行的一个Web应用。

tomcat 8.5.61的默认server.xml的配置如下:



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

        
        

        
        

        
        

        
        

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

下面来简单的认识一下核心组件(标签)的作用以及配置。本文以tomcat 8.5.61版本为主。

2 Server

Server标签是server.xml文件的根标签,代表整个tomcat的Servlet容器,时tomcat的核心组件,是Tomcat实例的顶层的org.apache.catalina.Server接口的抽象。

Server标签的属性表示 servlet 容器的一个整体的特征。常见属性如下:

属性名 描述
className 要使用的Java 实现类全路径名,指定的类必须实现org.apache.catalina.Server.Server 接口。如果未指定类名,则将使用标准实现,即org.apache.catalina.core.StandardServer
address tomcat监听shutdown命令的TCP/IP地址,如未指定,则默认为localhost
port tomcat监听shutdown命令的TCP/IP端口号,默认为8005。设置为-1,表示禁止通过端口关闭Tomcat,此时shutdown.bat命令不能使用。如果一台及其启动多个tomcat实例,该端口应该不一致。
shutdown 通过指定的地址(address)和端口(port)关闭tomcat时所需发送的终止字符串,默认为“SHUTDOWN”,修改shutdown的值,对shutdown.bat的使用无影响。

Server标签内部可以配置一个或者多个Listener标签,一个或者多个Service标签以及一个GlobalNamingResources标签。

2 Listener

一个Listener标签表示配置的一个tomcat的监听器组件。一个监听器负责监听特定的事件,当特定事件触发时,Listener会捕捉到该事件并做出相应处理。

Listener可嵌在Server、Engine、Host、Context标签内,不得将任何其他标签元素嵌套在监听器标签中。某些特殊类型的监听器仅用于嵌套在特定标签中,默认配置的监听器都是在Server标签内。Listener通常用于监听Tomcat的启动和关闭事件。

所有监听器都有的属性如下:

属性名 描述
className 要使用的Java 监听器实现类全路径名,指定的类必须实现org.apache.catalina.LifecycleListener 接口。

本文使用的tomcat版本中,默认开启的五个监听器配置如下:

Tomcat的核心组件以及server.xml配置全解【一万字】_第2张图片

常见的监听器介绍如下:

  1. VersionLoggerListener :版本日志记录生命周期监听器。当Tomcat启动时,该监听器记录Tomcat、Java和操作系统的信息。该类型的监听器必须只能嵌套在Server标签中,并且必须是配置的第一个监听器。
  2. AprLifecycleListener :APR 生命周期监听器。Tomcat启动时检查APR库,如果存在则加载。APR,即Apache Portable Runtime,是Apache可移植运行库,可以实现高可扩展性、高性能,以及与本地服务器技术更好的集成。该类型的监听器必须只能嵌套在Server标签中。Tomcat将以JNI的形式调用Apache HTTP服务器的核心动态链接库来处理文件读取或网络传输操作,从而大大地提高Tomcat对静态文件的处理性能。
  3. JreMemoryLeakPreventionListener:JRE 内存泄漏防护监听器。这个监听器会导致每小时就执行一次full GC操作,因此可以直接关闭这个监听器,或者添加gcDaemonProtection="false"属性来进制监听。该类型的监听器必须只能嵌套在Server标签中。
  4. GlobalResourcesLifecycleListener:全局资源生命周期监听器。通过该监听器,可以初始化< GlobalNamingResources/>标签中定义的全局JNDI资源;如果没有该监听器,任何全局资源都不能使用。该类型的监听器必须只能嵌套在Server标签中。
  5. ThreadLocalLeakPreventionListener:ThreadLocal泄漏防护监听器。当一个Web应用(context标签)停止时,该监听器器将触发执行器池中的线程更新,以避免线程本地相关内存泄漏。当线程执行完任务被收回线程池时,活跃线程会一个一个的更新。只有当Web应用(context标签)的renewThreadsWhenStoppingContext属性设置为true时,该监听器才有效。
  6. SecurityListener:安全生命周期监听器。当 Tomcat 启动时,该监听器将执行许多安全检查,并防止 Tomcat 在检查失败时启动。默认情况下未启用该侦听器。
  7. JasperListener:在Web应用启动之前初始化Jasper,Jasper是JSP引擎,把JVM不认识的JSP文件解析成java文件,然后编译成class文件供JVM使用。

3 GlobalNamingResources

全局命名资源组件,定义服务器的全局JNDI资源,所有的应用程序都可以引用。通常可以包含三个子标签:Environment、Resource、ResourceEnvRef。

JNDI(Java Naming and Directory Interface)多用于java的数据库连接中,我们常见的就是JDBC,在JDBC中,连接数据库需要用户名、用户名密码和数据库名称等参数,将来如果这三个参数中的任何一个修改,则整个程序中相关的地方都需要修改,简直是牵一发而动全身,因此出现JNDI技术。

在JNDI中,将连接数据库需要的用户、用户密码和数据库名称等JDBC引用的参数定义为一个整体(即这个整体中包含JDBC要用到类库、数据库驱动程序、用户、用户密码等),然后为这个整体设置一个名称,这个整体保存在应用程序之外的文件中,这样以后连接数据库的时候直接在程序中引用这个整体的名称即可,无论用户、用户密码怎么变换,只要这个整体的名称不变,我们仅要修改这个外部的整体的用户和用户密码,而无需修改整个程序。这里的这个整体就是JNDI数据源(JNDI资源)。对于数据库来说,JNDI数据源避免了程序与数据库之间的紧耦合,使应用更加易于配置、易于部署。

3.1 Environment

Environment标签可以用于配置全部项目的环境变量。比如:

<GlobalNamingResources ...>
...
<Environment name="maxExemptions" value="10"
       type="java.lang.Integer" override="false"/>
...
GlobalNamingResources>

它表示配置一个名为maxExemptions的Integer类型的环境变量,值为10。如果想要在具体的Web应用中引用该常量,那么在具体应用的Context标签下,使用ResourceLink标签引用该Environment资源,global属性就是该Environment的name属性名字。

这等同于在web应用的/WEB-INF/web.xml文件中的如下配置:

<env-entry>
  <env-entry-name>maxExemptionsenv-entry-name>
  <env-entry-value>10env-entry-value>
  <env-entry-type>java.lang.Integerenv-entry-type>
env-entry>

在Java代码中使用如下方式读取:

Context initCtx = null;
initCtx = new InitialContext();
Context envCtx = (Context)initCtx.lookup("java:comp/env");
Integer n = (Integer)envCtx.lookup("maxExemptions");

3.2 Resource

Resource标签可以用于配置各种全局数据源,最常见的就是用户数据库连接JNDI源。下面表示通过JNDI配置一个数据库数据源。

<GlobalNamingResources>       
    <Resource 
      name="DbSource" 
      username="admin"
      password="123456" 
      maxIdle="30" 
      maxActive="50"
      maxWait="5000"
      type="javax.sql.DataSource"
      driverClassName="com.mysql.jdbc.Driver" 
      url="jdbc:xxx" />
GlobalNamingResources>

然后在Web应用(context标签)下通过ResourceLink标签引用数据源:

<ResourceLink global="DbSource" name="DbSource" type="javax.sql.DataSource"/>

随后在Spring配置文件中可以配置引用JNDI数据源:

<beans>
  <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName">
        <value>java:/comp/env/ DbSourcevalue>
    property> 
  bean>
beans>

也可以使用Java代码获取:

//获得对数据源的引用:
Context ctx = new InitalContext();
DataSource ds = (DataSource)ctx.lookup("java:comp/env/DbSource");
//获得数据库连接对象:
Connection con = ds.getConnection();
//返回数据库连接到连接池:
con.close();

3.2.1 manager

Tomcat manager是Tomcat自带的、使用HTML界面的、管理Tomcat自身以及部署在Tomcat上的应用的web应用。

Tomcat的核心组件以及server.xml配置全解【一万字】_第3张图片

manager需要使用用户登陆并根据角色分配权限,角色和用户在tomcat-users.xml中配置。tomcat的tomcat-users.xml文件中默认没有配置任何用户信息:

Tomcat的核心组件以及server.xml配置全解【一万字】_第4张图片

tomcat-users.xml文件中的配置信息是tomcat8在server.xml中默认配置了的一个用户数据库数据源来加载的:


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

该示例表示定义了一个名为UserDataBase的全局JNDI数据源,使用容器管理该Resource,该数据源为加载tomcat-users.xml文件至内存中而定义的用于用户授权的数据库。然后在认证文件tomcat-users.xml中就可以配置可以访问Manager App和Host Manager页面的用户以及权限。在Engine标签下可以通过Realm标签来引用配置的数据源,resourceName属性的值就是Resource标签的name属性值。

上面的配置中role标签用来配置角色,user标签用来配置用户。如果我们在tomcat-users.xml中添加如下配置:

在这里插入图片描述

表示登陆用户名为admin,用户密码为123456,用户权限为admin-gui和admin-script,admin-gui表示允许访问 Host Manager的html接口(即URL路径为/host-manager/html/*),admin-script表示允许访问 Host Manager的纯文本接口(即URL路径为/host-manager/text/*)。此时我们就可以访问Host Manager页面。

Tomcat的核心组件以及server.xml配置全解【一万字】_第5张图片

对于Manager App页面,我们则需要配置如下几个权限:

  1. manager-gui:允许访问html接口(即URL路径为/manager/html/*)。
  2. manager-script:允许访问纯文本接口(即URL路径为/manager/text/*)。
  3. manager-jmx:允许访问JMX代理接口(即URL路径为/manager/jmxproxy/*)。
  4. manager-status:允许访问Tomcat只读状态页面(即URL路径为/manager/status/*)。

manager-gui、manager-script、manager-jmx均具备manager-status的权限,也就是说,manager-gui、manager-script、manager-jmx三种角色权限无需再额外添加manager-status权限,即可直接访问路径/manager/status/*。

4 Service

包含一个Engine和多个Connector的服务组件,表示org.apache.catalina.Service接口,用于对外提供Web服务。不同的Connector接收不同的客户端请求,多个Connector共用一个Engine来处理所有Connector接收到的请求。

Server中可以包括多个Service标签,Service标签内部不能直接定义< Value/>组件。tomcat8的默认配置中包含一个名为Catalina的Service组件。

Tomcat的核心组件以及server.xml配置全解【一万字】_第6张图片

Service的所有实现都支持以下属性:

属性名 描述
className 要使用的Java实现类全路径名,指定的类必须实现org.apache.catalina.Service接口。如果未指定类名,则将使用标准实现,即org.apache.catalina.core.StandardService
name Service组件的名字,必须唯一

5 Executor

Executor即线程池执行器,一个Service中可以配置多个命名线程池,可以由其他组件共享使用,一般来说,使用线程池的是Connector组件,用于处理Http请求,要使用指定的线程池执行器,组件需要通过executor属性指定对应线程池的name属性。

为了使Connector能正常使用线程池,Executor元素应该放在Connector前面。

执行器的所有实现都支持以下属性:

属性名 描述
className 要使用的Java 实现类全路径名,指定的类必须实现org.apache.catalina.Executor 接口。如果未指定类名,则将使用标准实现,即org.apache.catalina.core.StandardThreadExecutor
name 执行器的名字,其他组件通过名字引用该执行器,因此该属性是必需的,并且必须是唯一的

默认执行器实现支持以下属性:

属性名 描述
threadPriority Executor内的线程的优先级,默认值为5(Thread.NORM_PRIORITY)
daemon Executor内的线程是否是后台线程,默认值true
namePrefix Executor创建的每个线程的名称前缀,线程池中线程名字为:namePrefix+ threadNumber
maxThreads Executor中最大活跃线程数,默认值200(Tomcat7和8都是) ,即处理请求的最大线程数。
minSpareThreads Executor中保持的最小线程数(无论是否是空闲状态),默认值是25
maxIdleTime Executor中空闲线程超时关闭的毫秒数(除非线程数小于或等于 minSpareThread)。默认值为 60000(1 分钟)
maxQueueSize 在Executor执行拒绝策略之前,可以排队等待执行的最大可运行任务数,即任务队列的最大长度。默认值为Integer.MAX_VALUE((2147483647)
prestartminSpareThreads 启动Executor时是否应立即预初始化minSpareThread线程,默认值为false
threadRenewalDelay 如果配置了ThreadLocalLeakPreventionListener(默认会配置),监听器,它将通知此Executor有关的以停止的Web应用(context),停止Web应用后,池中的线程将重建。threadRenewalDelay表示重建线程的时间间隔,重建线程池内的线程时,为了避免线程同时重建,每隔threadRenewalDelay(毫秒)重建一个线程,默认值为1000,设置为负数则不重建

6 Connector

一个Connector标签代表一个与客户端实际交互的组件,负责接收客户端请求和返回响应结果。Connector标签位于Service标签下,一个Service标签可以包含多个Connector标签。

在tomcat程序中,Connector将会为每个请求创建Request和Response对象,然后分配线程让Engine(Servlet实例)来处理这个请求,并把产生的Request和Response对象传给Engine,当Engine处理完请求后,也会通过Connector将响应返回给客户端。可以说,Servlet容器处理请求,是需要Connector进行调度和控制的,Connector是Tomcat处理请求的主干之一。

我们着重要掌握连接器的属性,面试的时候经常问的tomcat的并发数量之类的都可以通过连接器设置。

连接器的所有实现都支持以下常用属性:

  1. port:连接器监听的请求端口,必须唯一。如果使用特殊值 0,则 Tomcat 将随机选择一个自由端口用于此连接器。
  2. protocol:连接器监听的请求协议类型,以及使用何种模式来接受和处理请求,默认为 HTTP/1.1类型,并且兼容HTTP1.0。tomcat6开始支持NIO,在tomcat8中增加了对NIO2的支持,tomcat8.5去除了BIO(org.apache.coyote.http11.Http11Protocol)的支持。对于HTTP协议,tomcat8中可以设置如下值:
    1. HTTP/1.1:默认值,使用的协议与Tomcat版本有关,并且会自动选取。在Tomcat7中,自动选取使用BIO或APR(如果找到APR需要的本地库,则使用APR,否则使用BIO);在Tomcat8中,自动选取使用NIO或APR(如果找到APR需要的本地库,则使用APR,否则使用NIO)。
    2. org.apache.coyote.http11.Http11NioProtocol:NIO,non blocking Java NIO connector
    3. org.apache.coyote.http11.Http11Nio2Protocol:NIO2,non blocking Java NIO2 connector
    4. org.apache.coyote.http11.Http11AprProtocol:APR,the APR/native connector.
    5. org.apache.coyote.http11.Http11Protocol:BIO,tomcat8.5已取消支持。
  3. 另外还可以设置使用AJP协议,即protocol=“AJP/1.3”。AJP协议是应用在Apache在反向代理tomcat的场景,Apache和tomcat之间就是使用AJP协议通信,它是一种二进制协议。
  4. redirectPort:如果当前连接器不支持SSL(HTTPS)请求,但是收到SSL(HTTPS)请求时,Catalina将重定向至指定端口的Connector。
  5. URIEncoding:用于解码URL的字符编码,如果未指定,则默认使用 UTF-8,除非org.apache.catalina.STRICT_SERVLET_COMPLIANCE系统属性设置为 true,在这种情况下,将使用 ISO-8859-1。因此,tomcat8的get请求中的中文参数不需要再另行处理乱码问题了(此前的低版本默认是ISO8859-1)。
  6. maxPostSize:POST方法能够提交的数据的最大大小(byte)。通过将此属性设置为小于0的值,则表示不限制。如果未指定该属性,则此属性设置为 2097152(2 MB)。请注意,失败请求筛选器FailedRequestFilter可用于拒绝超过此限制的请求。
  7. enableLookups:如果要需要在调用request.getRemoteHost()时执行 DNS 查找以返回远程客户端的实际主机名,那么需要设置为 true。设置为 false 表示会跳过 DNS 查找,并且以String 形式返回 IP 地址(从而提高性能)。默认情况下为false,将禁用 DNS 查找。
  8. allowTrace:用于配置服务器能够处理用户的HAED/TRACE请求。如果未指定,则此属性设置为 false,表示不能。

除了上面的属性之外,标准 HTTP 连接器(NIO, NIO2 and APR/native)还支持下面的常见属性:

  1. connectionTimeout:此连接器在建立连接之后等待请求URI的超时时间(毫秒),使用值 -1 表示无超时时间,默认值为60000(即 60秒)。当client与tomcat建立连接之后,在"connectionTimeout"时间之内,仍然没有得到client的请求数据,此时连接将会被断开。
  2. keepAliveTimeout:此连接器在关闭连接之前将等待另一个 HTTP 请求的超时时间(毫秒)。默认值是使用已为connectionTimeout属性设置的值,使用值 -1 表示无超时时间。
  3. maxConnections:tomcat在任何给定时间能同时接收和处理的最大连接数(不一定会被立即处理)。当Tomcat接收的连接数达到maxConnections时,Acceptor线程不会读取Accept队列中的连接;则Acceptor线程会一直阻塞着,直到Tomcat接收的连接数小于maxConnections。如果设置为-1,则连接数不受限制。
    1. 默认值因连接器类型而异。对于 NIO 和 NIO2,默认值为 10000,而BIO的默认值为maxThreads(如果配置了Executor,则默认值是Executor的maxThreads)。对于 APR/native,默认值为 8192,并且如果配置的值不是1024的倍数,maxConnections 的实际值将减少到1024的最大倍数。
  4. acceptCount:当同时连接数超过maxConnections时,系统会继续接收连接,但是传入的连接请求将在Accept等待队列等待而不会被Accepter拉取。该属性表示Accept等待队列的长度,如果等待队列也满了,那么收到的任何请求都将被直接被拒绝(返回connection refused)。默认值为100。
    1. 所以说,tomcat的可同时接收的最大连接数为maxConnections+acceptCount,对于BIO来说就是300
  5. maxThreads:每一次HTTP请求到达Web服务并建立连接之后,tomcat都会尝试创建一个线程来处理该请求。该属性表示此连接器可以创建的最大请求处理线程数,因此它决定连接器真正的可同时处理的用户请求的最大数量。如果未指定,则此属性默认设置为200。如果该Connector绑定了Executor,这个值会被忽略,因为该Connector将使用绑定的Executor,而不是内置的线程池来执行任务。
  6. executor:对 Executor 标签中name的引用。如果设置了此属性,并且存在指定的命名执行器,则该连接器将使用指定的执行器线程池,并且将忽略所有其他默认线程池属性,如果设置了默认执行器的属性,那么将报告一个-1来表示不会使用设置的属性。如果没有为连接器指定共享执行器,则连接器将使用专用的内部执行器提供线程池。
    1. 默认执行器线程命名通常是http-nio-,或者http-bio-。
  7. threadPriority:连接器的内部执行器中的请求处理线程的优先级。默认值为 5(java.lang.Thread.NORM_PRIORITY常量)。
  8. minSpareThreads:连接器的内部执行器保持的最小线程数(无论是否是空闲状态),默认值是10。
  9. SSLEnabled:设置此连接器是否开启SSL(HTTPS)的支持,如果需要开启,请将此值设置为 true。默认值为 false。将此值设置为 true 时,还需要设置scheme和secure这两个属性,即scheme=“https” secure=“true”。
  10. maxHttpHeaderSize:HTTP请求、响应头信息的最大大小,以字节为单位指定。如果未指定,此属性将设置为 8192 bytes(即8 KB)。

在tomcat8的默认配置中,只开放了一个Connector,其他的Connector则被注释了:

Tomcat的核心组件以及server.xml配置全解【一万字】_第7张图片

根据上面的属性,这个开放出来的Connector表示:客户端可以通过8080端口号使用HTTP/1.1协议(兼容HTTP1.0)访问tomcat,建立连接之后等待请求URI的超时时间为20000ms(即 20秒),并且当出现HTTPS请求时,该HTTPS请求将被转发至端口号为8443的Connector(从注释中可以看到端口号为8443的Connector设置了SSLEnabled=“true”,即支持处理HTTPS请求)。

http协议默认端口号为80,也就是说在URL中不给出端口号时就表示使用80端口。当然你也可以修改为其它端口号。当把端口号修改为80后,在浏览器中只需要输入:http://localhost就可以访问tomcat主页了。

7 Engine

Engine(引擎)表示一个与某个Service关联的请求处理组件,它接收并处理来自该Service中全部Connectors连接器接收到并封装的来自客户端的请求,并返回给连接器的已完成响应,以最终在通过连接器将响应传输回客户端。

Engine可以看作Servlet容器,即container。 由org.apahce.catalina.Engine接口定义。一个Service中有且只能有一个Engine组件。

Engine的所有实现都支持以下常见属性:

属性名 描述
name Engine的名称,用于日志和错误信息。在同一服务器中使用多个 Service 元素时,必须为每个Engine分配一个唯一的名称。
defaultHost 默认host主机名,当发往本机的请求指定的host名称不存在或者未指定时,一律使用defaultHost指定的host进行处理,因此此名称必须与内部的一个Host标签元素的name属性匹配。
jvmRoute 必须在负载平衡方案中使用的标识符,以启用session相关性。 主要是应用于tomcat集群中的session共享,会在一次会话中添加该值,获得session sticky
className 指定org.apache.catalina.Engine接口的实现类全路径名,默认值为org.apache.catalina.core.StandardEngine

在tomcat8中,默认的Engine配置为:

在这里插入图片描述

8 Host

Host是Engine的子容器,Engine中可以包含1个或多个Host组件,Engine组件的defaultHost属性必须与其中一个Host的name属性一致。对应着org.apache.catalina.Host接口。

Host表示一个虚拟主机,可以包含(管理)一个或多个Web应用(Host内部的一个Context代表一个Web应用),并负责安装、展开、启动和结束每个Web应用。配置多个Host可以让一个tomcat支持从不同的域名访问Web应用。

Host 的所有实现都支持以下常见属性:

属性名 描述
name 虚拟主机名。一般情况下,指定主机名需要是在DNS服务器中注册的网络名。localhost是DNS服务器中已经注册好的localhost对应着127.0.0.1,因此不需要我们手动注册。 如果是本地测试,Windows系统中,可以在‪C:\Windows\System32\drivers\etc\hosts文件中添加域名映射。
appBase 此虚拟主机的应用程序基础目录,这里指定目录的路径名,该目录下可能包含要在此虚拟主机上部署的 Web 应用程序。可以指定绝对路径名,也可以指定相对于tomcat基础目录的路径名。如果未指定,默认值为“webapps”。该属性主要用于Web 应用程序的自动识别和部署。
autoDeploy 指示 Tomcat 在 运行时应定期检查新的或更新的 Web 应用程序。如果为true,Tomcat 会定期检查 appBase 和 xmlBase 目录,并部署找到的任何新的 Web 应用程序或上下文 XML 描述符。更新的 Web 应用程序或上下文 XML 描述符将触发 Web 应用程序的重新加载。标志的值默认为 true。有关详细信息,请参阅自动应用程序部署。
className 指定org.apache.catalina.Host接口的实现类全路径名,默认值为org.apache.catalina.core.StandardHost
startStopThreads 此Host主机用于并行启动/发布子Context标签(Web应用)的线程数。如果开启自动部署,那么将使用同一个线程池来部署新的Web应用。指定为0,表示将使用Runtime.getRuntime().availableProcessors()数量的线程。负值将导致使用Runtime.getRuntime().availableProcessors()+startStopThreads的线程数量,如果结果小于1,在这种情况下将使用 1 个线程。如果未指定,将使用默认1个线程,用于部署Host下的所有Web项目。如果Host下的Web项目较多,由于只有一个线程负责部署这些项目,因此这些项目将依次部署,最终导致Tomcat的启动时间较长。此时,修改startStopThreads值,增加Host部署Web项目的并行线程数,可降低Tomcat的启动时间。

Host的标准实现是org.apache.catalina.core.StandardHost,它还支持以下常见附加属性:

属性名 描述
unpackWARs 指示是否将代表Web应用的WAR文件解压;如果为true,则先解压然后运行解压的Web应用,如果为false,直接使用WAR文件运行Web应用。

在tomcat8中,默认的Host配置为:

在这里插入图片描述

它表示虚拟主机名为localhost,应用程序基础目录为一个相对路径,即tomcat目录下的webapps目录,并且支持自动解压应用的War包,支持自动发布和更新项目。

因此我们启动一个新的tomcat8,它的默认访问URL前缀应该是localhost:8080。

8.1 Context

Context(上下文)代表一个运行在特定虚拟主机(Host)中运行的 Web 应用程序。一个Host内可以有0个或者多个Context。

对应着org.apache.catalina.Context接口。通过配置Context标签可以手动将其他路径的Web应用配置到tomcat中。

Context的所有实现都支持以下常见属性:

  1. path
    1. 此 Web 应用程序的虚拟上下文路径。与每个请求 URI 的开头字符串匹配,用以选择适当 Web 应用程序来处理特定的URI。一个主机(Host)内的所有上下文(Context)路径必须是唯一的。比如某个context设置path=“test”,那么请求URI前缀为http://localhost:8080/test才能访问该应用内部的资源。
    2. 如果指定空字符串""的上下文路径,则表示该Context为此主机的默认的Web 应用程序,该应用程序将处理没有分配到其他上下文中的所有请求。
    3. 一个Host中应该有一个Context的path="",用于处理与任何其他上下文路径不匹配的所有请求。
  2. docBase
    1. 此web应用程序的物理根目录,若该路径是相对路径的话,则是相对于appBase而言,若是绝对路径,则与appBase无关。
    2. 比如指定某个Context的docBase =“test”,那么表示对应的web应用根目录为CATALINA_HOME/webapps/test
  3. reloadable
    1. 是否支持重新加载web应用程序类,默认为false。如果这个属性设为true,Tomcat服务器在运行时会监视在WEB-INF/classes和Web-INF/lib目录下的class文件的改变,如果监视到有class文件被,更改,服务器自重新加载该Web应用。
    2. 在开发环境下,reloadable设置为true便于调试;但是在生产环境中设置为true会给服务器带来性能压力,因此reloadable参数的默认值为false。
  4. cookies
    1. 是否通过Cookie来支持Session会话(这需要客户端支持Cookie),默认值为true。
  5. crossContext
    1. 如果要在此应用程序中调用 ServletContext.getContext()返回在此虚拟主机上运行的其他Web应用程序的请求调度程序,请设置为true。默认设置为 false,使 getContext()方法始终返回 null。
    2. 设置为true时,利用可以访问其他项目的ServletContext对象的特性,该Web项目的Session信息可以共享给同一host下的其他Web项目。
  6. className
    1. 指定org.apache.catalina.Context接口的实现类全路径名,默认值为org.apache.catalina.core.StandardContext。

上下文的标准实现是org.apache.catalina.core.StandardContext。它支持以下附加常见属性:

属性名 描述
unpackWAR 指示是否将代表Web应用的WAR文件解压;如果指定为true,则通过所在Host的同名unpackWAR属性确定;如果为false,则所在Host的同名unpackWAR属性将被覆盖,并且不解包,直接使用WAR文件运行Web应用。如果未指定,则默认值为 true。
useNaming 指示是否支持JNDI,默认值为了true

8.2 Web应用的自动部署

tomcat可以自动部署Web应用,具体在哪里配置的呢?

我们需要配置Host组件的deployOnStartup或者autoDeploy属性。如果deployOnStartup或者autoDeploy设置为true,则tomcat启动自动部署:当检测到新的Web应用或Web应用的更新时,会触发应用的部署或重新部署。二者的主要区别在于,deployOnStartup为true时,Tomcat在启动时检查Web应用,且检测到的所有Web应用视作新应用;autoDeploy为true时,Tomcat在运行时定期检查新的Web应用或Web应用的更新。除此之外,二者的处理相似。

另外,还需要配置自动部署检查的目录,可以通过Host标签的appBase和xmlBase属性配置。appBase属性指定Web应用所在的目录,默认值是“webapps”,这是一个相对路径,代表Tomcat根目录下webapps文件夹。

xmlBase属性则是指定Web应用的XML配置文件所在的目录,默认值为conf/< engine_name>/< host_name>,例如第一部分的例子中,主机localhost的xmlBase的默认值是$TOMCAT_HOME/conf/Catalina/localhost

一个Web应用可能包括以下文件:XML配置文件,WAR包,以及一个应用目录(该目录包含Web应用的文件结构);其中XML配置文件位于xmlBase指定的目录,WAR包和应用目录位于appBase指定的目录。

Tomcat按照如下的顺序进行扫描,来检查应用更新:

  1. 扫描虚拟主机指定的xmlBase下的XML配置文件
  2. 扫描虚拟主机指定的appBase下的WAR文件
  3. 扫描虚拟主机指定的appBase下的应用目录

8.3 自动部署与Context

自动部署模式下,appBase目录中的Web应用不需要配置Context,tomcat会自动扫描appBase中的WAR包和应用目录来创建Context。
就算手动配置了Context,也不需要配置docBase和path属性。

  1. 自动部署模式下,tomcat会自动扫描appBase中的WAR包和应用目录来作为docBase属性值,如果手动指定了,返回可能会造成问题。
  2. 自动部署模式下,appBase中的Web应用不能指定path属性,path属性由配置文件的文件名、WAR文件的文件名或应用目录的名称自动推导出来。

比如,tomcat8的webapps中的默认有一下Web应用:

Tomcat的核心组件以及server.xml配置全解【一万字】_第8张图片

我们不必要单独为它们配置Context,它们的path就是对应的项目目录名,即docs、examples、host-manager、manager。对于名称为ROOT的目录,则该Web应用看作是虚拟主机默认的Web应用,此时path属性推导为””

因此,我们访问locahost:8080,实际上就是访问ROOT应用下的资源,而访问locahost:8080/docs,实际上就是访问docs应用下的资源。

8.4 静态部署Web应用

我们的项目默认都是放到webapps下面,此时称为自动部署,我们在学习了Context之后,现在可以将Web应用放在其他地方法,通过手动配置Context标签,也能让tomcat可以找到它,部署的应用称为外部应用。通过Context部署的项目称为静态部署。

假设有一个Web应用目录为G:\work\hello,这时我们需要通过tomcat访问,那么我们可以在Server.xml中配置Context标签:

<Context docBase="G:\work\hello" path="" reloadable="true" />

reloadable属性的用法与自动部署时相同。静态部署时,也可以显式指定path属性,但是仍然受到了严格的限制:只有当自动部署完全关闭(deployOnStartup和autoDeploy都为false)或docBase不在appBase中时,才可以设置path属性。

还有一种方法,在conf/catalana/localhost目录下创建一个hello.xml文件,在该文件中编写< Context/>标签,在标签中指明Web目录地址。

<Context docBase="G:\work\hello"/>	

此时path属性自动推导。

9 tomcat的请求查找流程

当请求被发送到Tomcat所在的主机时,如有多个Web应用,如何确定最终哪个Web应用来处理该请求呢?大概流程图如下:

Tomcat的核心组件以及server.xml配置全解【一万字】_第9张图片

其中index.html表示hello应用中的静态资源路径,通过该路径可以直接访问静态资源,而servlet/Aservlet则表示hi应用中的动态资源Servlet的映射路径,通过该路径可以找到对应的Servlet,随后即可处理请求。

9.1 根据协议和端口号选定Service和Engine

Service中的Connector组件可以接收特定端口和特定类型的请求,因此,当Tomcat启动时,Service组件就会监听特定的端口。当请求进来时,Tomcat便可以根据协议和端口号选定处理请求的Service;Service一旦选定,Engine也就确定。

tomcat8默认的Service配置监听8080端口的HTTP请求。

通过在Service中配置多个Connector或者在Server中配置多个Service,可以实现通过不同的端口号来访问同一台机器上部署的不同应用。

9.2 根据域名或IP地址选定Host

Service确定后,Tomcat在Service内部的Engine中寻找name属性值与域名/IP地址匹配的Host处理该请求。如果没有找到,则使用Engine中指定的defaultHost来处理该请求。

tomcat8默认的Engine内部只有一个Host,name为locathost,并且defaultHost属性为locathost,因此该Service的所有请求都交给该Host处理。

9.3 根据URI选定Context(Web应用)

选定Host之后,用于处理每个 HTTP 请求的 Web 应用程序由 Catalina 根据将请求 URI 的最长前缀与每个Context的上下文路径path来匹配,如果与某个Context的path一致,那么表示该请求将选择该Context对应的Web应用程序来处理,如果没有与任何一个Context的path匹配成功,那么将使用path=""的Conext。

在选择Context后,该上下文将根据对应的 Web 应用程序在部署时指定的 servlet 映射路径,选择适当的 servlet 来处理传入请求。

参考资料:

  1. Apache Tomcat 8 Configuration Reference
  2. 深入理解-Tomcat-(二)-从宏观上理解-Tomcat-组件及架构
  3. 深度解读Tomcat中的NIO模型
  4. 详解tomcat的连接数与线程池

如有需要交流,或者文章有误,请直接留言。另外希望点赞、收藏、关注,我将不间断更新各种Java学习博客!

你可能感兴趣的:(Java,EE,server.xml,tomcat,javaweb)