Tomcat系列文章:http://www.cnblogs.com/f-ck-need-u/p/7576137.htmlhtml
该示例经过设置虚拟主机来提供web服务,由于是入门示例,因此设置极其简单,只需修改$CATALINA_HOME/conf/server.xml文件为以下内容便可,本文的tomcat安装在/usr/local/tomcat下,所以$CATALINA_HOME=/usr/local/tomcat
。其中大部分都采用了默认设置,只是在engine容器中添加了两个Host容器。前端
<?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" enableLookups="false" />
<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容器做为虚拟主机 -->
<!-- 定义一个在$CATALINA_HOME以外的虚拟主机 -->
<Host name="www.longshuai.com" appBase="/www/longshuai" unpackWARs="true" autoDeploy="true">
<Context path="" docBase="/www/longshuai" reloadable="true" />
<Context path="/xuexi" docBase="xuexi" reloadable="true" />
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="longshuai_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" />
</Host>
<!-- 定义一个在$CATALINA_HOME/webapps下的虚拟主机 -->
<Host name="www.xiaofang.com" appBase="webapps/xiaofang" unpackWARs="true" autoDeploy="true">
<Context path="" docBase="" reloadable="true" />
<Context path="/xuexi" docBase="xuexi" reloadable="true" />
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs" prefix="xiaofang_access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b" />
</Host>
<!-- 默认虚拟主机localhost,可不修改 -->
<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>
除了engine中定义的默认localhost虚拟主机,另外布置了两个虚拟主机www.longshuai.com和www.xiaofang.com,它们的程序目录分别为/www/longshuai和$CATALINA_HOME/webapps/xiaofang,因此须要提早创建好这两个目录。另外,在context中定义了docBase,对于uri路径/xuexi,它的文件系统路径分别为/www/longshuai/xuexi目录和$CATALINA_HOME/webapps/xiaofang/xuexi,因此也要在上面两个程序目录中定义好xuexi目录。除此以外,还分别为这3个虚拟主机定义了日志,它们的路径为相对路径logs,相对于$CATALINA_HOME。java
再提供appBase目录和docBase目录。mysql
mkdir -p /www/longshuai/xuexi
mkdir -p /usr/local/tomcat/webapps/xiaofang/xuexi
再提供测试用的index.jsp文件。内容大体以下,分别复制到如下四个目录中:
/www/longshuai/
/www/longshuai/xuexi/
/usr/local/tomcat/webapps/xiaofang/
/usr/local/tomcat/webapps/xiaofang/xuexi nginx
并将out.println的输出内容分别稍做修改,使可以区分读取的是哪一个index.jsp。web
<%@ page language="java" %>
<%@ page import="java.util.*" %>
<html>
<body>
<% out.println("hello world from longshuai Root"); %>
</body>
</html>
最后重启catalina。sql
catalina.sh stop catalina.sh start
再测试主机上添加www.{longshuai,xiaofang}.com的host记录。例如在windows上,在C:\Windows\System32\drivers\etc\hosts中添加以下记录:数据库
192.168.100.22 www.longshuai.com www.xiaofang.com
在浏览器中进行测试,结果以下:apache
以下两图:上面的图是tomcat组件体系的简图,下面的图是Service组件细化后的图。windows
tomcat高度模块化,各个模块之间有嵌套的父子关系。若是使用配置文件来描述,能够大体简化为以下:
<server>
<service>
<connector PORT />
<engine>
<host name=www.a.com appBase=/www/a >
<context path="" docBase=/www/a />
<context path="/xuexi" docBase=/www/a/xuexi />
</host>
<host>
<context />
</host>
</engine>
</service>
</server>
其中:
server
组件是管理tomcat实例的组件,能够监听一个端口,今后端口上能够远程向该实例发送shutdown关闭命令。service
组件是一个逻辑组件,用于绑定connector和container,有了service表示能够向外提供服务,就像是通常的daemon类服务的service。能够认为一个service就启动一个JVM,更严格地说,一个engine组件才对应一个JVM(定义负载均衡时,jvmRoute就定义在Engine组件上用来标识这个JVM),只不过connector也工做在JVM中。connector
组件是监听组件,它有四个做用:
container
是容器,它是一类组件,在配置文件(如server.xml)中没有体现出来。它包含4个容器类组件:engine容器、host容器、context容器和wrapper容器。engine
容器用于从connector组件处接收已创建的TCP链接,还用于接收客户端发送的http请求并分析请求,而后按照分析的结果将相关参数传递给匹配出的虚拟主机。engine还用于指定默认的虚拟主机。host
容器定义虚拟主机,因为tomcat主要是做为servlet容器的,因此为每一个webapp指定了它们的根目录appBase。context
容器主要是根据path和docBase获取一些信息,将结果交给其内的wrapper组件进行处理(它提供wrapper运行的环境,因此它叫上下文context)。通常来讲,都采用默认的标准wrapper类,所以在context容器中几乎不会出现wrapper组件。wrapper
容器对应servlet的处理过程。它开启servlet的生命周期,根据context给出的信息以及解析web.xml中的映射关系,负责装载相关的类,初始化servlet对象init()、执行servlet代码service()以及服务结束时servlet对象的销毁destory()。executor
组件为每一个Service组件提供线程池,使得各个connector和Engine能够从线程池中获取线程处理请求,从而实现tomcat的并发处理能力。必定要注意,Executor的线程池大小是为Engine组件设置,而不是为Connector设置的,Connector的线程数量由Connector组件的acceptorThreadCount属性来设置。若是要在配置文件中设置该组件,则必须设置在Connector组件的前面,以便在Connector组件中使用`executor`属性来引用配置好的Executor组件。若是不显式设置,则采用Connector组件上的默认配置,默认配置以下:
根据上面描述的tomcat组件体系结构,处理请求的大体过程其实很容易推导出来:
Client(request)-->Connector-->Engine-->Host-->Context-->Wrapper(response data)-->Connector(response header)-->Client
撇开tomcat做为servlet容器的行为。它和apache、nginx的功能大体都能对应上。例如以nginx为例,如下是nginx提供web服务时的配置结构:
server {
listen PORT;
server_name www.a.com; # 对应于<host name=www.a.com>
location / { # 对应于context path=""
root html; # 对应于docBase
}
location /xuexi { # 对应于context path="/xuexi"
root html/xuexi;
}
}
connetcor组件相似于nginx的listen指令。host容器相似于nginx的server指令,host容器中的name属性至关于nginx的server_name指令。engine组件则没有对应配置项,不过在nginx一样有engine的功能,例如默认的虚拟主机,分析URL来判断请求交给哪一个虚拟主机处理等。context容器至关于location指令,context容器的path属性至关于location的uri匹配路径,docBase至关于location的中的root指令,即DocumentRoot。
tomcat做为简单的web服务程序大体如此,但它的核心毕竟是处理servlet和jsp,它必须得管理好每一个webapp。所以,对于tomcat来讲,必需要掌握部署webapp的方式。在tomcat上部署webapp时,必需要理解context的概念。对于tomcat而言,每一个context都应该算是一个webapp,其路径由docBase决定,该目录存放的是归档的war文件或未归档的webapp相关文件,而host容器中的appBase则是虚拟主机整理webapp的地方,一个appBase下能够有多个webapp,即多个context。
这两货虽然意义很明确,但"潜规则"很严重。如下面的配置为例。
<host name=www.a.com appBase=/www/a >
<context path="" docBase=/www/a />
<context path="/xuexi" docBase=/www/a/xuexi />
</host>
appBase是虚拟主机存放webapp的目录,它能够是相对路径,也能够是绝对路径。若是是相对路径,则相对于$CATALINA_HOME,严格并准确地说是$CATALINA_BASE。
path是URI的匹配路径,至关于nginx的location后的路径。tomcat要求每一个虚拟主机必须配置一个空字符串的path,该条context做为URI没法被明确匹配时的默认context,它至关于nginx中location / {}
的做用。
docBase则是每一个webapp的存放目录(或者是已归档的war文件),它能够是相对路径,也能够是绝对路径,提供相对路径时它相对于appBase。该目录通常在appBase的目录下,但并不规定必定要放在appBase下。对于web服务来讲,它至关于nginx的root指令,但对于webapp来讲,一个context就至关于一个webapp,而docBase正是webapp的路径。
"潜规则"在于默认的context如何提供。有如下几种状况:
<context path="" docBase=webappPATH>
,此时默认context的处理路径为webappPATH。<context path="">
,但却没给定docBase属性,此时该默认context处理路径为appBase/ROOT目录,注意ROOT为大写。path=""
的context时,即host容器中没有明确的path="",此时将隐式定义一个默认context,处理路径为appBase/ROOT目录。context path context name 推断出的docBase路径
--------------------------------------------------
/foo /foo foo
/foo/bar /foo/bar foo/bar
Empty String Empty String ROOT
显然,没有给定path=""或缺乏docbase时,都以ROOT做为目录。如下是几个定义示例:
# 虚拟主机中没有定义任何context,将以appBase下的ROOT做为默认处理路径
<Host appBase="webapps">
</Host>
# 没有定义path=""的context,但定义了path非空的context,也将以ROOT做为默认处理路径
# 若是下面的Context容器中省略docBase属性,则推断出该context的docBase路径为appBase/xuexi
<Host appBase="webapps">
<Context path="/xuexi" docBase="webappPATH" />
</Host>
# 某个context定义了path="",该context将做为默认context
# 但该默认context若是没有定义docBase,将推断出其docBase路径为appBase/ROOT
<Host appBase="webapps">
<Context path="" docBase="webappPATH" />
</Host>
# 某个context定义了path="",该context将做为默认context
# 下面的默认context明肯定义了docBase
<Host appBase="webapps">
<Context path="" docBase="webappPATH" />
</Host>
举个直观的例子,若是某个Host配置以下。
<Host name="www.xiaofang.com" appBase="/www/xiaofang" unpackWARs="true" autoDeploy="true">
<Context path="/xuexi" docBase="xuexi" reloadable="true" />
</Host>
那么浏览器访问http://www.xiaofang.com:8080/xuexi/
将请求/www/xiaofang/xuexi/index.jsp
。
因为没有定义path=""的Context组件,所以浏览器访问http://www.xiaofang.com:8080
将请求/www/xiaofang/ROOT/index.jsp
。注意,是ROOT目录。
若是加上<Context path="" docBase="" reloadable="true" />
,则访问http://www.xiaofang.com:8080
将请求/www/xiaofang/index.jsp
。注意,不是ROOT目录,而是相对于appBase的根目录,即/www/xiaofang。
尽管本文解释了一大堆关于appBase和docBase的设置,但通常都会采用大众所熟知的配置方式:appBase设置为"webapps",即$CATALINA_HOME/webapps,而docBase设置为webapps下的webapp应用名。这样配置不只符合eclipse部署webapp时默认的部署目录结构(eclipse部署应用时,将WebContent下的内容复制到docBase下,将servlet java源代码编译后的class文件复制到WEB-INF/classes目录下),更利于维护webapp和相关配置。例如:
<Context docBase="MyWeb" path="/MyWeb" reloadable="true" />
<Context docBase="SecondWeb" path="/SecondWeb" reloadable="true" />
<Context docBase="WEB" path="/WEB" reloadable="true" />
但这样的配置有个缺点,由于项目名称通常都会带有大写字母,使得在浏览器访问时,也要带有大写字母。例如输入http://www.a.com/MyWeb/index.jsp
。所以,可采用另外一种配置方式:设置Host的appBase为webapps下的某个目录,而后在path上配置uri匹配路径。以下:
<Host name="www.xiaofang.com" appBase="webapps/MyWeb" unpackWARs="true" autoDeploy="true">
<Context path="/xuexi" docBase="xuexi" reloadable="true" />
<Context path="" docBase="" reloadable="true" />
</Host>
webapp有特定的组织格式,是一种层次型目录结构,一般包含了servlet代码文件、jsp页面文件、类文件、部署描述符文件等等。
这些文件多是以目录的形式存放,也可能会打包成各类归档格式的文件,如jar、war等。但jsp有规定,在web应用程序的根目录下,通常要有下面几个目录:
每一个webapp要想被tomcat加载,一种方法是程序目录放在$catalina.home/webapps下,另外一种方式是配置该webapp相关的context配置,使tomcat能找到此webapp。正如前文所说,webapp目录通常都会放在$catalina.home/webapps下。
简单部署示例:
(1)对于war类归档程序:将归档文件复制到$CATALINA_BASE/webapps/目录中,并重启tomcat便可,tomcat会自动展开war归档。例如官方提供了一个sample.war做为tomcat学习初级示例( https://tomcat.apache.org/tomcat-8.5-doc/appdev/sample/sample.war ),下载后只需将其放入webapps下便可。
(2)在测试tomcat的过程当中,不少时候是未归档程序,这时能够手动建立目录来实现部署。须要建立的目录有webapps/yourapp,此目录下还要建立WEB-INF目录,在WEB-INF目录中还要建立classes和lib目录。而后将jsp文件放在对应目录下便可,如写一个测试的index.jsp放在yourapp目录下。而对于已经开发完毕的webapp,由于eclipse在发布测试webapp时已经设置好目录,所以只要将webapp的目录复制到webapps目录下便可。
tomcat配置文件中配置的是各个组件的属性,全局配置文件为$CATALINA_HOME/conf/server.xml,主要的组件有如下几项:Server,Service,Connector,Engine,Host,Alias,Context,Valve等。配置完配置文件后须要重启tomcat,但在启动后必定要检查tomcat是否启动成功,由于即便出错,不少时候它都不会报错,可从监听端口判断。
配置方法见官方手册,在页面的左边有各个组件的连接。
tomcat的配置文件都是xml文件,如下是xml文件的常见规则:
<?xml version="1.0" encoding="UTF-8"?>
。<!-- XXX -->
,这能够是单行注释,也能够多行注释,只要先后注释符号能对应上,中间的内容都是注释。<!-- 单行定义的方式 -->
<NAME key=value />
<!-- 多行定义的方式 -->
<NAME key=value>
</NAME>
下面个组件的配置中有些地方使用了相对于$CATALINA_BASE的相对路径,它和$CATALINA_HOME小有区别。若是只有一个tomcat实例,则它们是等价的,都是tomcat的安装路径。若是有多个tomcat实例,则$CATALINA_HOME表示的是安装路径,而$CATALINA_BASE表示的是各实例所在根目录。关于tomcat多实例,见running.txt中对应的说明。
server组件定义的是一个tomcat实例。默认定义以下:
<Server port="8005" shutdown="SHUTDOWN">
</Server>
它默认监听在8005端口以接收shutdown命令。要启用多个tomcat实例,将它们监听在不一样的端口便可。这个端口的定义为管理员提供一个关闭实例的便捷途径,能够直接telnet至此端口使用SHUTDOWN命令关闭此实例。不过基于安全角度的考虑,一般不容许远程进行。
Server的相关属性:
className
:用于实现此组件的java类的名称,这个类必须实现接口org.apache.catalina.Server。不给定该属性时将采用默认的标准类org.apache.catalina.core.StandardServer;address
:监听端口绑定的地址。如不指定,则默认为Localhost,即只能在localhost上发送SHUTDOWN命令;port
:接收shutdown指令的端口,默认仅容许经过本机访问,默认为8005;shutdown
:经过TCP/IP链接发往此Server用于实现关闭tomcat实例的命令字符串。在server组件中可嵌套一个或多个service组件。
定义了service就能提供服务了。service组件中封装connector和container,它同时也表示将此service中的connector和container绑定起来,即由它们组成一个service向外提供服务。默认定义以下:
<Service name="Catalina">
</Service>
Service相关的属性:
className
:用于实现service的类名,这个类必须实现org.apache.catalina.Service接口。不给定该属性时将采用默认的标准类org.apache.catalina.core.StandardService。name
:此service的显示名称,该名称主要用于在日志中进行标识service。通常来讲可有可无,默认为Catalina。执行器定义tomcat各组件之间共享的线程池。在之前,每一个connector都会独自建立本身的线程池,但如今,能够定义一个线程池,各组件均可以共享该线程池,不过主要是为各connector之间提供共享。注意,executor建立的是共享线程池,若是某个connector不引用executor建立的线程池,那么该connector仍会根据本身指定的属性建立它们本身的线程池。
链接器必需要实现org.apache.catalina.Executor接口。它是一个嵌套在service组件中的元素,为了挑选所使用的connector,该元素还必须定义在connector元素以前。
默认的定义以下:
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-" maxThreads="150" minSpareThreads="4"/>
其中该组件的属性有:
className
:用于实现此组件的java类的名称,这个类必须实现接口org.apache.catalina.Executor。不给定该属性时将采用默认的标准类org.apache.catalina.core.StandardThreadExecutor;name
:该线程池的名称,其余组件须要使用该名称引用该线程池。标准类的属性包括:
threadPriority
:线程优先级,默认值为5。daemon
:线程是否以daemon的方式运行,默认值为true。namePrefix
:执行器建立每一个线程时的名称前缀,最终线程的名称为:namePrefix+threadNumber。maxThreads
:线程池激活的最大线程数量。默认值为200。minSpareThreads
:线程池中最少空闲的线程数量。默认值为25。maxIdleTime
:在空闲线程关闭前的毫秒数。除非激活的线程数量小于或等于minSpareThreads的值,不然会有空闲线程的出现。默认值为60000,即空闲线程须要保留1分钟的空闲时间才被杀掉。maxQueueSize
:可执行任务的最大队列数,达到队列上限时的链接请求将被拒绝。prestartminSpareThreads
:在启动executor时是否当即建立minSpareThreads个线程数,默认为false,即在须要时才建立线程。例如在connector中指定所使用的线程池,方式以下:
<Connector executor="tomcatThreadPool" port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
链接器用于接收客户端发送的请求并返回响应给客户端。一个service中能够有多个connector。有多种connector,常见的为http/1.1,http/2和ajp(apache jserv protocol)。在tomcat中,ajp链接协议类型专用于tomcat前端是apache反向代理的状况下。
所以tomcat能够扮演两种角色:
Tomcat应该考虑工做情形并为相应情形下的请求分别定义好须要的链接器才能正确接收来自于客户端的请求。
此处暂先介绍HTTP/1.1链接器的属性设置。ajp后文再作介绍。
HTTP链接器表示支持HTTP/1.1协议的组件。设置了该链接器就表示catalina启用它的独立web服务功能,固然,确定也提供它必须的servlets和jsp执行功能。在一个service中能够配置一个或多个链接器,每一个链接器均可以将请求转发给它们相关联的engine以处理请求、建立响应。
每一个流入的请求都须要一个独立的线程来接收。当并发请求数量超出maxThreads指定的值时,多出的请求将被堆叠在套接字中,直到超出acceptCount指定的值。超出accpetCount的请求将以"connection refused"错误进行拒绝。
默认的定义以下:
<Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" />
HTTP链接器的属性实在太多,详细配置方法见官方手册。一般定义HTTP链接器时必须定义的属性只有"port"。
address
:指定链接器监听的地址,默认为全部地址,即0.0.0.0。maxThreads
:支持的最大并发链接数,默认为200;若是引用了executor建立的共享线程池,则该属性被忽略。acceptCount
:设置等待队列的最大长度;一般在tomcat全部处理线程均处于繁忙状态时,新发来的请求将被放置于等待队列中;maxConnections
:容许创建的最大链接数。acceptCount和maxThreads是接受链接的最大线程数。存在一种状况,maxConnections小于acceptCount时,超出maxConnections的链接请求将被接收,但不会与之创建链接。port
:监听的端口,默认为0,此时表示随机选一个端口,一般都应该显式指定监听端口。protocol
:链接器使用的协议,用于处理对应的请求。默认为HTTP/1.1,此时它会自动在基于Java NIO或APR/native链接器之间进行切换。定义AJP协议时一般为AJP/1.3。redirectPort
:若是某链接器支持的协议是HTTP,当接收客户端发来的HTTPS请求时,则转发至此属性定义的端口。connectionTimeout
:等待客户端发送请求的超时时间,单位为毫秒,默认为60000,即1分钟;注意,这时候链接已经创建。keepAliveTimeout
:长链接状态的超时时间。超出该值时,长链接将关闭。enableLookups
:是否经过request.getRemoteHost()进行DNS查询以获取客户端的主机名;默认为true,应设置为false防止反解客户端主机;compression
:是否压缩数据。默认为off。设置为on时表示只压缩text文本,设置为force时表示压缩全部内容。应该在压缩和sendfile之间作个权衡。useSendfile
:该属性为NIO的属性,表示是否启用sendfile的功能。默认为true,启用该属性将会禁止compression属性。当协议指定为HTTP/1.1时,默认会自动在NIO/APR协议处理方式上进行按需切换。如要显式指定协议,方式以下:
<connector port="8080" protocol="HTTP/1.1">
<connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol">
<connector port="8080" protocol="org.apache.coyote.http11.Http11Nio2Protocol">
<connector port="8080" protocol="org.apache.coyote.http11.Http11AprProtocol">
其中NIO是C/C++的非阻塞IO复用模型在JAVA中的IO实现,NIO2即AIO是异步NIO,即异步非阻塞IO:
NioProtocol :non blocking Java NIO connector
Nio2Protocol:non blocking Java NIO2 connector
AprProtocol :the APR/native connector
它们之间的异同点以下表所示:
Java Nio Connector | Java Nio2 Connector | APR/native Connector | |
---|---|---|---|
Classname | Http11NioProtocol | Http11Nio2Protocol | Http11AprProtocol |
Tomcat Version | 6.x onwards | 8.x onwards | 5.5.x onwards |
Support Polling | YES | YES | YES |
Polling Size | maxConnections | maxConnections | maxConnections |
Read Request Headers | Non Blocking | Non Blocking | Non Blocking |
Read Request Body | Blocking | Blocking | Blocking |
Write Response Headers and Body | Blocking | Blocking | Blocking |
Wait for next Request | Non Blocking | Non Blocking | Non Blocking |
SSL Support | Java SSL or OpenSSL | Java SSL or OpenSSL | OpenSSL |
SSL Handshake | Non blocking | Non blocking | Blocking |
Max Connections | maxConnections | maxConnections | maxConnections |
下面是一个定义了多个属性的SSL链接器:
<Connector port="8443" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" acceptCount="100" debug="0" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" />
engine是service组件中用来分析协议的引擎机器,它从一个或多个connector上接收请求,并将请求交给对应的虚拟主机进行处理,最后返回完整的响应数据给connector,经过connector将响应数据返回给客户端。
只有一个engine元素必须嵌套在每一个service中,且engine必须在其所须要关联的connector以后,这样在engine前面的connector均可以被此engine关联,而在engine后面的connector则被忽略,由于一个service中只容许有一个engine。
定义方式大体以下:
<Engine name="Catalina" defaultHost="localhost">
</Engine>
<Engine name="Standalone" defaultHost="localhost" jvmRoute="TomcatA">
</Engine>
经常使用的engine属性有:
className
:实现engine的类,该类必须实现org.apache.catalina.Engine接口。不给定该属性时将采用默认的标准类org.apache.catalina.core.StandardEngine。defaultHost
:指定处理请求的默认虚拟主机。在Engine中定义的多个虚拟主机的主机名称中至少有一个跟defaultHost定义的主机名称同名。name
:Engine组件的名称,用于记录日志和错误信息,可有可无的属性,可随意给定。jvmRoute
:在启用session粘性时指定使用哪一种负载均衡的标识符。全部的tomcat server实例中该标识符必须惟一,它会追加在session标识符的尾部,所以能让前端代理老是将特定的session转发至同一个tomcat实例上。engine是容器中的顶级子容器,其内能够嵌套一个或多个Host做为虚拟主机,且至少一个host要和engine中的默认虚拟主机名称对应。除了host,还能够嵌套releam和valve组件。
host容器用来定义虚拟主机。engine从connector接收到请求进行分析后,会将相关的属性参数传递给对应的(筛选方式是从请求首部的host字段和虚拟主机名称进行匹配)虚拟host进行处理。若是没有合适的虚拟主机,则传递给默认虚拟主机。所以每一个容器中必须至少定义一个虚拟主机,且必须有一个虚拟主机和engine容器中定义的默认虚拟主机名称相同。
大体定义方式以下:
<Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true">
</Host>
经常使用属性说明:
className
:实现host容器的类,该类必须实现org.apache.catalina.Host接口。不给定该属性时将采用默认的标准类org.apache.catalina.core.StandardHost。name
:虚拟主机的主机名,忽略大小写(初始化时会自动转换为小写)。可使用前缀星号通配符,如"*.a.com"。使用了星号前缀的虚拟主机的匹配优先级低于精确名称的虚拟主机。appBase
:此Host的webapps目录,即webapp部署在此虚拟主机上时的存放目录。包括非归档的web应用程序目录和归档后的WAR文件的目录。使用相对路径时基于$CATALINA_BASE。xmlBase
:部署在此虚拟主机上的context xml目录。startStopThreads
:启动context容器时的并行线程数。若是使用了自动部署功能,则再次部署或更新时使用相同的线程池。autoDeploy
:在Tomcat处于运行状态时放置于appBase目录中的应用程序文件是否自动进行deploy或自动更新部署状态。这等于同时开启了deployOnStartup属性和reload/redeploy webapp的功能。触发自动更新时将默认重载该webapp。默认为true。unpackWars
:在执行此webapps时是否先对归档格式的WAR文件解压再运行,设置为false时则直接执行WAR文件;默认为true。设置为false时会损耗性能。workDir
:该虚拟主机的工做目录。每一个webapp都有本身的临时IO目录,默认该工做目录为$CATALINA_BASE/work。大多数时候都只需设置虚拟主机名称name和appBase属性便可,其他采用默认,默认时会自动部署webapp。有时候还须要管理多个站点名称,即主机别名。可使用Alias为Host指定的主机名定义主机别名。如:
<Host name="web.a.com" appBase="webapps" unpackWARs="true">
<Alias>www.a.com</Alias>
</Host>
自动部署指的是自动装载webapp以提供相关webapp的服务。
connector和container是整个tomcat的心脏,而context则是container的心脏,更是tomcat心脏的心脏。它是真正管理servlet的地方,它的配置影响了servlet的工做方式。
一个context表明一个webapp。servlet中规定,每一个webapp都必须基于已归档的WAR(WEB application archive)文件或基于非归档相关内容所在目录。
catalina基于对请求URI与context中定义的path进行最大匹配前缀的规则进行挑选,从中选出使用哪一个context来处理该HTTP请求。这至关于nginx的location容器,catalina的path就至关于location的path,它们的做用是相同的。
每一个context都必须在虚拟主机容器host中有一个惟一的context name。context的path不须要惟一,由于容许同一个webapp不一样版本的共存部署。此外,必需要有一个context的path为0长度的字符串(如<Context path="" docBase="ROOT"/>
),该context是该虚拟主机的默认webapp,用于处理全部没法被虚拟主机中全部context path匹配的请求(固然,不定义也能够,此时将自动隐式提供,见前文所述)。
关于context name,它是从context path推断出来的,不只如此,其他几个属性如context basefile name也是由此推断出来的。规则以下:
例如:
context path context name basefile name deploy examples
-----------------------------------------------------------------
/foo /foo foo foo.xml,foo.war,foo
/foo/bar /foo/bar foo#bar foo#bar.xml,foo#bar.war,foo#bar
Empty String Empty String ROOT ROOT.xml,ROOT.war,ROOT
配置context时,强烈建议不要定义在server.xml中,由于定义在conf/server.xml中时,只能经过重启tomcat来重载生效,也就是说没法自动部署应用程序了。虽然说官方如此推荐,但大多数人出于习惯和方便,仍是会直接写在server.xml中,这并无什么问题,无非是重启一下而已。
能够考虑定义在/META-INF/context.xml中,若是此时设置了copyXML属性,在部署时会将此context.xml复制到$CATALINA_BASE/conf/enginename/hostname/下,并重命名为"basefile name.xml"。也能够直接定义在$CATALINA_BASE/conf/enginename/hostname/下的.xml文件中,该路径的xml优先级高于/META-INF/context.xml。
还能够定义默认的context.xml文件,包括两种:(1)定义在$CATALINA_BASE/conf/context.xml中,该默认context对全部webapp都生效;(2)定义在$CATALINA_BASE/conf/[enginename]/[hostname]/context.xml.default中,该默认context只对该虚拟主机中的全部webapp生效。
定义方式大体以下:
<Host name="www.a.com" appBase="webapps" unpackWARs="true" autoDeploy="true">
<Context path="" docBase="ROOT"/>
<Context path="/bbs" docBase="web/bbs" reloadable="true"/>
</Host>
其中第一个context的path为空字符串,表示它是默认的context。当浏览器中输入www.a.com时,因为没法匹配第二个context,因此被默认即第一个context处理,当浏览器中输入www.a.com/bbs时,将被第二个context处理,它将执行web/bbs所对应的webapp,并返回相关内容。
在context容器中能够定义很是多的属性,详细内容见官方手册,如下是常见的几个属性:
className
:实现host容器的类,该类必须实现org.apache.catalina.Context接口。不给定该属性时将采用默认的标准类org.apache.catalina.core.StandardContext。cookies
:默认为true,表示启用cookie来标识session。docBase
:即DocumentRoot,是该webapp的context root,即归档WAR文件所在目录或非归档内容所在目录。能够是绝对路径,也能够是相对于该webapp appBase的相对路径。path
:定义webapp path。注意,当path=""时,表示默认的context;另外只有在server.xml中才须要定义该属性,其余全部状况下都不能定义该属性,由于会根据docBase和context的xml文件名推断出path。reloadable
:是否监控/WEB-INF/class和/WEB-INF/lib两个目录中文件的变化,变化时将自动重载。在测试环境下该属性很好,但在真实生产环境部署应用时不该该设置该属性,由于监控会大幅增长负载,所以该属性的默认值为false。wrapperClass
:实现wrapper容器的类,wrapper用于管理该context中的servlet,该类必须实现org.apache.catalina.Wrapper接口,若是不指定该属性则采用默认的标准类。xmlNamespaceAware
:和web.xml的解析方式有关。默认为true,设置为false能够提高性能。xmlValidation
:和web.xml的解析方式有关。默认为true,设置为false能够提高性能。realm定义的是一个安全上下文,就像是以哪一种方式存储认证时的用户和组相关的数据库。有多种方式能够实现数据存放:
下面是一个常见的使用UserDatabase的配置:
<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>
下面是一个使用JDBC方式获取用户认证信息的配置:
<Realm className="org.apache.catalina.realm.JDBCRealm" debug="99" driverName="org.gjt.mm.mysql.Driver" connectionURL="jdbc:mysql://localhost/authority" connectionName="test" connectionPassword="test" userTable="users" userNameCol="user_name" userCredCol="user_pass" userRoleTable="user_roles" roleNameCol="role_name" />
Valve中文意思是阀门,相似于过滤器,它能够工做于Engine和Host/Context之间、Host和Context之间以及Context和Web应用程序的某资源之间。一个容器内能够创建多个Valve,并且Valve定义的次序也决定了它们生效的次序。
有多种不一样的Valve:
其中RemoteHostValve和RemoteAddrValve能够分别用来实现基于主机名称和基于IP地址的访问控制,控制自己能够经过allow或deny来进行定义,这有点相似于Apache的访问控制功能。以下面的Valve实现了仅容许本机访问/probe:
<Context privileged="true" path="/probe" docBase="probe">
<Valve className="org.apache.catalina.valves.RemoteAddrValve" allow="127\.0\.0\.1"/>
</Context>
其中相关属性定义有:
另一个经常使用的Valve为AccessLogValve,定义方式大体以下:
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
其中prefix和suffix表示日志文件的前缀名称和后缀名称。pattern表示记录日志时的信息和格式。