server.xml in tomcat
1. 预备知识
在本文开始之前,我们来看一下官方对Tomcat的定义:
The Apache Tomcat® software is an open source implementation of the Java Servlet, JavaServer Pages, Java Expression Language and Java WebSocket technologies.
Apache Tomcat®是一个开源软件,实现了Java Servlet、JavaServer Pages、Java Expression Language、Java WebSocket等技术。
Java ™ Servlet Specification中对Servlet的定义为:
A servlet is a Java™ technology-based Web component, managed by a container, that generates dynamic content.
Servlet是一个基于Java技术的Web组件,托管在容器中,用于生成动态内容。
对容器的定义为:
Containers, sometimes called servlet engines, are Web server extensions that provide servlet functionality.
容器(也称Servlet引擎)指能够提供Servlet功能的Web服务器扩展程序。
2. server.xml
本文使用的Tomcat版本为v8.5.50。
从现在开始,我们用$CATALINA_HOME表示Tomcat的安装目录,例如:/home/samson/apache-tomcat-8.5.50/server.xml指$CATALINA_HOME/conf/server.xml
2.1 <Server>
A Server element represents the entire Catalina servlet container.
<Server>用来表示整个Catalina Servlet容器,所以它必须是server.xml中唯一的最外层元素。<Server>包含4个属性:
className,用来表示所使用的实现类,必须实现org.apache.catalina.Server接口。如果省略,则使用默认的实现org.apache.catalina.core.StandardServer。address,指定接收停机指令的TCP/IP地址,默认为localhost。port,指定接收停机指令的端口号。值为-1时,则默认关闭停机端口。shutdown,指定关机指令。
2.2 <Service>
A Service element represents the combination of one or more Connector components that share a single Engine component for processing incoming requests.
<Service>是<Server>的子标签之一,是共享同一个<Engine>的一个或多个<Connector>的组合。<Service>包含2个属性:
className,用来表示所使用的实现类,必须实现org.apache.catalina.Service接口。如果省略,则使用默认的实现org.apache.catalina.core.StandardService。name,<Service>的标识名,同一个<Server>内的所有<Service>的name不可重复。
2.3 <Engine>
The Engine element represents the entire request processing machinery associated with a particular Catalina Service. It receives and processes all requests from one or more Connectors, and returns the completed response to the Connector for ultimate transmission back to the client.
每个<Service>都包含且仅包含一个<Engine>,表示其所在的<Service>的请求处理机制。它接收并处理当前<Service>中所有<Connector>收到的请求,并返回完整的响应。<Engine>包含如下6个属性:
backgroundProcessorDelayclassName,用来表示所使用的实现类,必须实现org.apache.catalina.Engine接口。如果省略,则使用默认的实现org.apache.catalina.core.StandardEngine。defaultHost,默认的主机名,无法匹配的请求将被重定向到该主机上。jvmRoutename,<Engine>的标识名。当<Server>中使用多个<Service>时,每个<Service>中的<Engine>名称都必须是唯一的。因此,一般将其名称设置为其所属的<Service>的名称。startStopThreads
在$CATALINA_HOME/conf中有与<Engine>同名的目录,用于存放它们独特的配置。
2.4 <Connector>
每个<Service>中可包含一个或多个<Connector>,表示接受请求和发送响应的端点。根据协议的不同,分为
- HTTP/1.1
- HTTP/2
- AJP
具体信息请参考:The HTTP Connector
2.5 <Host>
The Host element represents a virtual host, which is an association of a network name for a server (such as "www.mycompany.com") with the particular server on which Tomcat is running.
每个<Engine>中可以有一个或多个<Host>,每个都表示一个不同的虚拟主机。每个<Engine>至少包含一个<Host>,并且必需通过defaultHost属性来指定一个默认<Host>。
客户端一般通过主机名来标识其要连接的服务器。客户端发起的请求头中会包含主机名,Tomcat通过请求头中的主机名选择与其匹配的主机,如果找不到匹配主机,则选择默认主机(即通过defaultHost指定的主机)。
从此刻起,用
$CATALINA_BASE指代设置的Tomcat的基准地址,如果未部署多个Tomcat实例,$CATALINA_BASE的值与$CATALINA_HOME一致。
<Host>的常用属性包括:
appBase,用来指定此虚拟主机的应用程序基本目录。可以是绝对路径,或到$CATALINA_BASE的相对路径。其默认值为$CATALINA_HOME/webappsname,通常设置为虚拟主机的网络名,与在DNS注册的名称一致。不区分大小写,tomcat会将其转为小写。
2.6 <Context>
The Context element represents a web application, which is run within a particular virtual host.
<Context>可以在<Host>中嵌套使用,用来表示一个Web应用程序。每个Web应用程序可以是Web Application Archive(WAR)文件,或包含特定结构的文件夹。关于Web应用程序更多的信息,请参考 Application Developer's Guide。
Catalina通过比较请求的URI和<Context>的context path来选择由哪个Web应用来处理这个请求。并且会根据Web应用程序中web.xml定义的规则,来选择某个Servlet来具体处理这个请求。每个<Host>中,所有<Context>的名称都必须唯一,但它们的context path却不必。而且,必须存在一个context path为空字符串(即长度为0)的<Context>,作为默认Web应用程序,例如$CATALINA/webapps/ROOT。默认Web应用程序用来处理无法与任何context path所匹配的请求。
并行部署
同一个context path可以同时部署同一个Web应用的多个版本,匹配请求URI的规则如下:
- 如果请求中不包含任何的会话信息,则选择最新版本
- 如果请求中包含会话信息,检索每个版本的会话管理器来查找匹配的会话,如果能找到,则使用相应的版本
- 如果请求总包含会话信息,担又检索不到匹配会话,则使用最新版本
命名方式
当<Host>进行autoDeploy或deployOnStartup时,context path会根据WAR文件、xml文件、或表示Web应用的目录生成。context path、context version、context name、base file name(指取出.xml、.war后缀的文件名)的关系如下:
context path |
context version |
context name |
base file name |
example file name |
|---|---|---|---|---|
| /foo | None | /foo | foo | foo.xml, foo.war, foo |
| /foo/bar | None | /foo/bar | foo#bar | foo#bar.xml, foo#bar.war, foo#bar |
| empty string | None | empty string | ROOT | ROOT.xml, ROOT.war, ROOT |
| /foo | 42 | /foo##42 | foo##42 | foo##42.xml, foo##42.war, foo##42 |
| /foo/bar | 42 | /foo/bar##42 | foo#bar##42 | foo#bar##42.xml, foo#bar##42.war, foo#bar##42 |
| empty string | 42 | ##42 | ROOT##42 | ROOT##42.xml, ROOT##42.war, ROOT##42 |
context version比较是按照字符串的方式进行的,即foo.war被认为是比foo##11.war旧的版本,foo#11.war被认为是比foo##2.war旧的版本。
如果不想让Tomcat根据base file name自动推断出context name等信息,可通过如下方式之一实现:
- 将
autoDeploy和deployOnStartup置为false,并在server.xml中定义所有的Web应用 - 把WAR文件或代表Web应用的目录文件放置在
<Host>的appBase目录之外,并在%CATALINA_HOME/conf/[engine_name]/context.xml,并用docBase指定。
如何定义一个Context
It is NOT recommended to place
<Context>elements directly in the server.xml file.
不建议在server.xml中直接用<Context>定义。
从此处开始,用$APP_BASE表示某个Web应用程序的根目录
$CATALINA_HOME/conf/server.xml的修改必须要重启Tomcat才能应用。Context可以分为两类:
Individual Context,定义在如下位置中:$APP_BASE/META-INF/context.xml,根据<Host>配置的属性copyXML,将把该文件拷贝到$CATALINA_HOME/conf/[engine name]/[host name]目录下,并重命名为[base file name].xml$CATALINA_HOME/conf/[engine name]/[host name]/[base file name].xml,该文件优先于任何$APP_BASE/META-INF/context.xml$CATALINA_HOME/conf/server.xml中的<Context>
Default Context,定义在如下位置中:$CATALINA_HOME/conf/context.xml,定义的元素会被所有的Web应用程序加载$CATALINA_HOME/conf/[engine name]/[host name]/context.xml.default,定义的元素会被当前<Host>上运行的所有Web应用程序加载
除了server.xml外,其他的每个文件都只能定义一个<Context>。更多具体的信息,请参考The Context Container。
2.7 <Realm>
<Realm>可以在<Engine>、<Host>或Context中嵌套使用,表示包含用户名、密码和角色信息的数据库,用于实现Container Managed Security。<Realm>的常用属性为:
className,用来表示所使用的实现类,必须实现org.apache.catalina.Realm接口。Tomcat提供多个标准实现:org.apache.catalina.realm.JDBCRealmorg.apache.catalina.realm.DataSourceRealmorg.apache.catalina.realm.JNDIRealmorg.apache.catalina.realm.UserDatabaseRealmorg.apache.catalina.realm.MemoryRealmorg.apache.catalina.realm.JAASRealmorg.apache.catalina.realm.CombinedRealmorg.apache.catalina.realm.LockOutRealmorg.apache.catalina.realm.NullRealm
关于<Realm>的更多详细信息,请参考The Realm Component。