转自: http://bbs.163jsp.com/posts/list/607.html
Apache Tomcat 是一款非常著名的开源 Servlet/JSP 容器,被用做 Java Servlet 和 JavaServer Pages 技术的官方参考实现。如果您要了解这两种技术的细节可以查阅参考资料。
让我们先来浏览一下 Tomcat 体系结构中的六个主要概念:
● Server
● Service
● Engine
● Host
● Connector
● Context
由于Tomcat体系结构的内容非常丰富,所以本文非常长。因此我们尽量的使每一部分尽可能自成一体,使您可以独立阅读。如果您不是想全面了解Tomcat 的体系结构,只是想解决某一部分的具体问题,那么我们建议您使用目录导航到相关的内容,而不必在其它的内容上花费宝贵的时间。
=============================================================================
Server
Server代表整个容器(container)。它可以包含一个或多个Service,还可以包含一个GlobalNamingResources。
值得注意的是在标准的Server接口中没有包括Lifecycle接口,但是在标准实现 org.apache.catalina.core.StandardServer中却实现了Lifecycle这个接口,这使得我们可以为Tomcat 的标准实现设置Listener。一般的方法是在conf/server.xml文件中加入:
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.solol.listener.XXXLifecycleListener" />
<Listener className="org.solol.listener.XXXLifecycleListener" />
:
:
:
</Server>
其中的XXXLifecycleListener为您自定义的LifecycleListener,而且必须要实现LifecycleListener接口。您可以在这里设置多个LifecycleListener,但要使用不同的名字。
由于在Tomcat的官方文档中没有显著的说明,所以这种使用Listener的方式没有体现在稍后给出的 体系结构图 中。
Server支持className,port和shutdown三个公共属性,而标准实现org.apache.catalina.core.StandardServer还可能支持一些扩展属性。详细的内容您可以查阅 这里 。
您可以通过稍后给出的 体系结构图 了解在整个Tomcat体系结构中Server所处的位置。
=============================================================================
Service
Service中可以含有一个或多个Connector,但只能含有一个Engine。这使得不同的Connector可以共享同一个Engine。同一个Server中的多个Service之间没有相关性。
值得注意的是在标准的Service接口中没有包括Lifecycle接口,但是在标准实现 org.apache.catalina.core.StandardService中却实现了Lifecycle这个接口,这使得我们可以为 Tomcat的标准实现设置Listener。
由于在Tomcat的官方文档中没有显著的说明,所以这种使用Listener的方式没有体现在稍后给出的 体系结构图 中。
Service支持className和name两个公共属性,而标准实现org.apache.catalina.core.StandardService还可能支持一些扩展属性。详细的内容您可以查阅 这里 。
您可以通过稍后给出的 体系结构图 了解在整个Tomcat体系结构中Service所处的位置。
=============================================================================
Engine
Engine负责接收和处理来自它所属的Service中的所有Connector的请求。
Engine 支持backgroundProcessorDelay、className、defaultHost、jvmRoute和name五个公共属性,而标准实现org.apache.catalina.core.StandardEngine还可能支持一些扩展属性。详细的内容您可以查阅 这里 。
您可以通过稍后给出的 体系结构图 了解在整个Tomcat体系结构中Engine所处的位置。
从图中可以看出Engine右边有四个不同颜色的小方块,它们表示Engine所支持的四个不同的特性。相同颜色的小方块可能也会出现在其它的地方,这表示在那里也支持相同的或相似的特性。每种特性的具体描述可以在文中的Special Features中找到。
从图中可以看出Engine下边有一个红色的圆角矩形,它们表示Engine所支持的一个内嵌组件。相同颜色的圆角矩形可能也会出现在其它的地方,这表示在那里也支持相同的或相似的内嵌组件。每种内嵌组件的具体描述可以在文中的Nested Components中找到。
=============================================================================
Host
Host表示一个虚拟主机,并和一个服务器的网络名关联。注意Engine中必须有一个Host的名字和Engine的defaultHost属性匹配。
有时候,网络管理员可能希望将多个网络名关联到一个虚拟主机,这可以通过下文介绍的Host Name Aliases特性完成。
Host 支持appBase、autoDeploy、backgroundProcessorDelay、className、deployOnStartup和 name六个公共属性,而标准实现org.apache.catalina.core.StandardHost还可能支持一些扩展属性。详细的内容您可以查阅这里。
您可以通过稍后给出的 体系结构图 了解在整个Tomcat体系结构中Host所处的位置。
从图中可以看出Host右边有八个不同颜色的小方块,它们表示Host所支持的八个不同的特性。相同颜色的小方块可能也会出现在其它的地方,这表示在那里也支持相同的或相似的特性。每种特性的具体描述可以在文中的Special Features中找到。
从图中可以看出Host下边有一个红色的圆角矩形,它们表示Host所支持的一个内嵌组件。相同颜色的圆角矩形可能也会出现在其它的地方,这表示在那里也支持相同的或相似的内嵌组件。每种内嵌组件的具体描述可以在文中的Nested Components中找到。
=============================================================================
Connector
Connector负责接收来自客户端(Client)的请求。比较常见的两个是 HTTP Connector 和 AJP Connector 。
您可以通过稍后给出的 体系结构图 了解在整个Tomcat体系结构中Connector所处的位置。
=============================================================================
Context
Context表示在虚拟主机中运行的web应用程序。一个虚拟主机中能够运行多个Context,它们通过各自的Context Path进行相互区分。如果Context Path为"",那么该web应用为该虚拟主机的默认的web应用。
目前可以通过四种方式将Context加入Host:
● $CATALINA_HOME/conf/context.xml,其中Context元素中的信息会被所有web应用程序加载
● $CATALINA_HOME/conf/[enginename]/[hostname]/context.xml.default,其中Context元素中的信息会被hostname主机下的所有web应用程序加载
● $CATALINA_HOME/conf/[enginename]/[hostname]/目录中所有以.xml为扩展名的文件,其中Context元素中的信息会被hostname主机下的所有web应用程序加载
● 如果通过上面的步骤没有找到,那么最后要从web应用程序的/META-INF/context.xml目录中查找
Context 支持backgroundProcessorDelay、className、cookies、crossContext、docBase、 override、privileged、path、reloadable和wrapperClass十个公共属性,而标准实现 org.apache.catalina.core.StandardContext还可能支持一些扩展属性。详细的内容您可以查阅这里。
您可以通过稍后给出的 体系结构图 了解在整个Tomcat体系结构中Context所处的位置。
从图中可以看出Context右边有十个不同颜色的小方块,它们表示Context所支持的十个不同的特性。相同颜色的小方块可能也会出现在其它的地方,这表示在那里也支持相同的或相似的特性。每种特性的具体描述可以在文中的Special Features中找到。
从图中可以看出Context下边有五个不同颜色的圆角矩形,它们表示Context所支持的五个内嵌组件。相同颜色的圆角矩形可能也会出现在其它的地方,这表示在那里也支持相同的或相似的内嵌组件。每种内嵌组件的具体描述可以在文中的Nested Components中找到。
=============================================================================
体系结构图
=============================================================================
Nested Components
=============================================================================
GlobalNamingResources
GlobalNamingResources 组件为 Server 定义全局 JNDI 资源。这些资源出现在 Server 的全局 JNDI 资源上下文中。这个上下文和每个 web 应用程序的 JNDI 上下文不同。在全局 JNDI 上下文中定义的资源在每个 web 应用程序的 JNDI 上下文中不可见,但是可以通过 Resource Links 来改变这种可见性。如果您要了解在 Tomcat 中如何使用 JNDI 资源可以查阅参考 http://tomcat.apache.org/tomcat-6.0-doc/jndi-resources-howto.html。
从前面给出的 体系结构图 中可以看出GlobalNamingResources右边有四个不同颜色的小方块,它们表示GlobalNamingResources所支持的四个不同的特性。相同颜色的小方块可能也会出现在其它的地方,这表示在那里也支持相同的或相似的特性。每种特性的具体描述可以在文中的Special Features中找到。
Realm
从前面给出的 体系结构图 中可以看出,Realm组件在Engine、Host和Context中都有支持。
Realm 是一个"数据库"存储着用户名、密码和角色信息。通过自定义Realm可以将Catalina集成到其它的环境。Engine、Host和Context 中的Realm可以被较低级别的容器继承,即Host继承Engine的Realm,Context继承Host的Realm,除非我们显示的禁止这种继承。
Realm支持className一个公共属性。Tomcat提供了多个实现:
● org.apache.catalina.realm.JDBCRealm
● org.apache.catalina.realm.DataSourceRealm
● org.apache.catalina.realm.JNDIRealm
● org.apache.catalina.realm.MemoryRealm
如果您要了解这些Realm的更多信息,可以查阅 这里 。
Loader
从前面给出的 体系结构图 中可以看出,Loader组件只在Context中都有支持。
Loader是web应用程序的类装载器。必须有一个类装载器按照Servlet Specification的要求从如下的位置装载类:
● 从web应用程序的/WEB-INF/classes目录装载
● 从web应用程序的/WEB-INF/lib目录中的jar文件中装载
● 从Catalina中装载对于所有web应用可见的资源
Loader元素应该嵌入到Context元素中,如果没有设置那么会自动创建一个默认的Loader。如果想更深入的了解Catalina实现的Loader可以查阅参考资料。
Loader支持className、delegate和reloadable三个公共属性,而标准实现org.apache.catalina.loader.WebappLoader还可能支持一些扩展属性。详细的内容您可以查阅 这里 。
Manager
从前面给出的 体系结构图 中可以看出,Manager组件只在Context中有支持。
Manager是session管理器(session manager),负责session的创建和维护。
Manager元素应该嵌入到Context元素中,如果没有设置那么会自动创建一个默认的Manager。
Manager 支持className和distributable两个公共属性,而标准实现 org.apache.catalina.session.StandardManager和 org.apache.catalina.session.PersistentManager还可能支持一些扩展属性。详细的内容您可以查阅 这里 。
Resources
从前面给出的 体系结构图 中可以看出,Resources组件只在Context中有支持。
Resources表示web应用程序的静态资源。这使得我们有可能实现non-filesystem based Resources。
Resources元素应该嵌入到Context元素中,如果没有设置那么会自动创建一个默认的基于文件系统的Resources。
Resources支持className一个公共属性,而标准实现org.apache.naming.resources.FileDirContext还可能支持一些扩展属性。详细的内容您可以查阅 这里 。
WatchedResource
从前面给出的 体系结构图 中可以看出,WatchedResource组件只在Context中都有支持。
WatchedResource用来告知Auto Deployer那些静态资源的更新需要被监控。如果被监控的资源被更新了那么该资源所对应的web应用将会被重新装载。这个元素的内容必须是一个String。
=============================================================================
Special Features
=============================================================================
Logging
从前面给出的 体系结构图 中可以看出,Logging特性在Engine、Host和Context中都有支持。这个特性使得我们可以区分日志记录的具体来源。
在Engine、Host和Context中的日志类别分别为:
● org.apache.catalina.core.ContainerBase.[enginename]
● org.apache.catalina.core.ContainerBase.[enginename].[hostname]
● org.apache.catalina.core.ContainerBase.[enginename].[hostname].[path]
其中中括号([])中为具体的名称。
Logging特性的实现是通过org.apache.catalina.core.ContainerBase来完成的。
Access Logs
从前面给出的 体系结构图 中可以看出,Access Logs特性在Engine、Host和Context中都有支持。
● Engine中的Access Logs记录所有Engine处理的请求的访问日志
● Host中的Access Logs记录所有Host处理的请求的访问日志
● Context中的Access Logs记录所有Context处理的请求的访问日志
一般的配置方法是在conf/server.xml文件的相关元素中加入:
<Engine ...>
...
<Valve className="org.apache.catalina.valves.AccessLogValve"
prefix="catalina_access_log." suffix=".txt" pattern="common"/>
...
</Engine>
上面的<Engine>,在Host中要被换成<Host>,在Context中要被换成<Context>。
Access Logs特性的实现是通过Tomcat的Value框架来完成的。
如果您要了解Access Log Valve设置的更多信息,可以查阅 这里 。
Lifecycle Listeners
从前面给出的 体系结构图 中可以看出,Lifecycle Listeners特性在Engine、Host和Context中都有支持。这个特性使得我们可以方便的进行生命周期的管理。
值得一提的是在Tomcat的标准实现中Server和Service也支持生命周期的管理,但是在官方文档中没有显著的说明,所以没有在图中体现出来。细节可以查阅Server和Service部分。
● Engine中的Lifecycle Listeners监听该Engine的生命周期事件(Eifecycle Event)
● Host中的Lifecycle Listeners监听该Host的生命周期事件(Eifecycle Event)
● Context中的Lifecycle Listeners监听该Context的生命周期事件(Eifecycle Event)
一般的配置方法是在conf/server.xml文件的相关元素中加入:
<Engine ...>
...
<Listener className="com.mycompany.mypackage.MyListener" ... >
...
</Engine>
上面的<Engine>,在Host中要被换成<Host>,在Context中要被换成<Context>。
另外,可以通过<Listener>元素为listener添加属性。
注意和Container Event区别。
Request Filters
从前面给出的 体系结构图 中可以看出,Request Filters特性在Engine、Host和Context中都有支持。
● Engine中的Request Filters过滤所有Engine处理的请求
● Host中的Request Filters过滤所有Host处理的请求
● Context中的Request Filters过滤所有Context处理的请求
一般的配置方法是在conf/server.xml文件的相关元素中加入:
<Engine ...>
...
<Valve className="org.apache.catalina.valves.RemoteHostValve"
allow="*.mycompany.com,www.yourcompany.com"/>
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
deny="192.168.1.*"/>
...
</Engine/>
上面的<Engine>,在Host中要被换成<Host>,在Context中要被换成<Context>。
Request Filters特性的实现是通过Tomcat的Value框架来完成的。
如果您要了解Remote Address Filter设置的更多信息,可以查阅 这里 。
如果您要了解Remote Host Filter设置的更多信息,可以查阅 这里 。
Automatic Application Deployment
从前面给出的 体系结构图 中可以看出,Automatic Application Deployment特性只在Host中都有支持。
如果使用Host的标准实现,同时deployOnStartup属性值为true(这是默认值),那么Catalina在首次启动时会自动完成下面的工作:
● $CATALINA_HOME/conf/[engine_name]/[host_name]目录下的所有XML文件都被假定含有<Context>元素。
● appBase 目录下的所有没有展开的war文件(没有展开的意思是没有和war文件名不包括.war扩展名对应的目录存在)会被自动展开,除非unpackWARs属性值为false。如果重新部署更新的war文件,在重起Tomcat之前要删除先前展开的目录(如果autoDeploy属性值为true那么只要删除先前展开的目录更新后的war文件就会自动展开)。
● 对于appBase中含有/WEB-INF/web.xml文件的任何子目录都会自动产生一个Context,不管该子目录是否在 conf/server.xml文件中出现过。这个新产生的Context将会根据DefaultContext的属性值进行设置,其context path为“/目录名”。如果目录名为ROOT,那么context path为“”。
因此要使用上面的规则需要将XML设置文件拷贝到$CATALINA_HOME/conf/[engine_name]/[host_name]目录下或将war文件和含有web应用的目录拷贝到appBase目录下。
自动部署(Auto Deployer)也会跟踪如下web应用程序的变化:
● 更新WEB-INF/web.xml文件将会使web应用程序重新加载
● 更新已展开的war文件会使web应用程序卸载(undeploy)(同时移除先前展开的目录)并重新部署(deployment)
● 更新XML设置文件会使web应用程序卸载(undeploy)(不移除任何展开的目录)并重新部署(deployment)
在使用自动部署的时候XML设置文件中的docBase要指向appBase目录之外。否则部署将很困难或应用程序会被部署两次。
如果要显示的定义context,那么需要关闭自动部署。否则相应的context将会部署两次,这可能会有问题。
Host Name Aliases
从前面给出的 体系结构图 中可以看出,Host Name Aliases特性只在Host中都有支持。
在一些时候,网络管理员会将多个网络名(在DNS服务器中)解析到同一个服务器。通常每一个网络名会对应到一个Host。不过有时候需要将多个网络名对应到一个Host,Host Name Aliases用来完成这个目标。
一般的配置方法是在conf/server.xml文件的相关元素中加入:
<Host name="www.mycompany.com" ...>
...
<Alias>mycompany.com</Alias>
...
</Host>
<Host>元素中可以嵌入一个或多个<Alias>元素。
Single Sign On
从前面给出的 体系结构图 中可以看出,Single Sign On特性只在Host中都有支持。
在一些时候,特别是在Portal环境下,可能会希望当用户访问一个虚拟主机下的多个web应用时只登陆一次,即所谓的单点登陆。
一般的配置方法是在conf/server.xml文件的相关元素中加入:
<Host name="localhost" ...>
...
<Valve className="org.apache.catalina.authenticator.SingleSignOn"
debug="0"/>
...
</Host>
Single Sign On操作遵循下面的规则:
● 该虚拟主机下的所有Web应用程序必须共享同一个Realm。在实践中通常通过为Host或(对应的Engine)嵌入Realm而不是为每一个Context嵌入相同的Realm来实现。
● 在用户访问该虚拟主机下的所有Web应用程序中的非保护资源时不需要验证。
● 在用户访问该虚拟主机下的所有Web应用程序中的保护资源时需要验证。
● 一旦被验证,就会对该虚拟主机下的所有Web应用程序有效,而不用每个应用程序单独验证。
● 如果用户从一个Web应用中退出,那么所有Web应用程序中的session都会失效。
● 使用SSO需要客户环境支持cookies。
Single Sign On特性的实现是通过Tomcat的Value框架来完成的。
如果您要了解Single Sign On设置的更多信息,可以查阅 这里 。
User Web Applications
从前面给出的 体系结构图 中可以看出,User Web Applications特性只在Host中都有支持。
许多Web服务器都可以处理如下形式的请求:
http://www.mycompany.com:8080/~craigmcc
其中craigmcc为系统的一位用户名。具体的处理过程和操作系统相关。
在类Unix或Linux等操作系统下配置方法如下:
<Host name="localhost" ...>
...
<Listener className="org.apache.catalina.startup.UserConfig"
directoryName="public_html"
userClass="org.apache.catalina.startup.PasswdUserDatabase"/>
...
</Host>
在Windows等操作系统下配置方法如下:
<Host name="localhost" ...>
...
<Listener className="org.apache.catalina.startup.UserConfig"
directoryName="public_html"
homeBase="c:\Homes"
userClass="org.apache.catalina.startup.HomesUserDatabase"/>
...
</Host>
这两种配置最主要的区别就是发现用户和为用户匹配路径。PasswdUserDatabase依据/etc/passwd发现用户而HomesUserDatabase依据homeBase="c:\Homes"发现用户。
User Web Applications是通过Listener(org.apache.catalina.startup.UserConfig)的方式实现的。即在Host启动时该Listener会被执行,它会为每一个发现的用户构建对应Context。
使用User Web Applications时需要考虑以下的一些问题:
● 依据DefaultContext来设置为每一个用户建立Context
● 可以使用多个Listener元素(在这么做之前您最好查阅一下UserConfig)
● 用户所对应的目录应该具有读写权限
Automatic Context Configuration
从前面给出的 体系结构图 中可以看出,Automatic Context Configuration特性只在Context中都有支持。
如果使用标准的Context实现,当Catalina启动或Web应用装载时,会按如下的步骤自动进行设置:
● 如果没有指定Loader元素,那么一个标准的Loader将会被设置
● 如果没有指定Manager元素,那么一个标准的Manager将会被设置
● 如果没有指定Resources元素,那么一个标准的Resources将会被设置
● 处理conf/web.xml文件
● 处理/WEB-INF/web.xml文件
● 如果设置了security constraints,那么一个对应的Authenticator会被创建
Context Parameters
从前面给出的 体系结构图 中可以看出,Context Parameters特性只在Context中有支持。
如下的两种配置等价,都是为Web配置初始参数:
<Context ...>
...
<Parameter name="companyName" value="My Company, Incorporated" override="false"/>
...
</Context>
<context-param>
<param-name>companyName</param-name>
<param-value>My Company, Incorporated</param-value>
</context-param>
Environment Entries
从前面给出的 体系结构图 中可以看出,Environment Entries特性在GlobalNamingResources和Context中都有支持。
如下的两种配置等价,都是为配置environment entry resources:
<GlobalNamingResources ...>
...
<Environment name="maxExemptions" value="10" type="java.lang.Integer" override="false"/>
...
</GlobalNamingResources>
<env-entry>
<env-entry-name>maxExemptions</param-name>
<env-entry-value>10</env-entry-value>
<env-entry-type>java.lang.Integer</env-entry-type>
</env-entry>
这里使用GlobalNamingResources表示environment entry resources对于所有Web应用程序可见。如果换成Context则表示只对相应Web应用程序可见。
Resource Definitions
从前面给出的 体系结构图 中可以看出,Resource Definitions特性在GlobalNamingResources和Context中都有支持。
如下的两种配置等价,都是为定义Resource:
<GlobalNamingResources ...>
...
<Resource name="jdbc/EmployeeDB" auth="Container" type="javax.sql.DataSource"
description="Employees Database for HR Applications"/>
...
</GlobalNamingResources>
<resource-ref>
<description>Employees Database for HR Applications</description>
<res-ref-name>jdbc/EmployeeDB</res-ref-name>
<res-ref-type>javax.sql.DataSource</res-ref-type>
<res-auth>Container</res-auth>
</resource-ref>
这里使用GlobalNamingResources表示Resource对于所有Web应用程序可见。如果换成Context则表示只对相应Web应用程序可见。
Resource Links
从前面给出的 体系结构图 中可以看出,Resource Links特性在GlobalNamingResources和Context中都有支持。
ResourceLink 元素用来将资源从全局上下文(global context)中连接到每个Web应用的上下文(per-web-application contexts)中。使用方式依据GlobalNamingResources和Context的不同分成两种:
<DefaultContext>
<ResourceLink name="bean/MyBeanFactory" global="bean/MyBeanFactory" type="com.mycompany.MyBean"/>
</DefaultContext>
<Context ...>
...
<ResourceLink name="linkToGlobalResource" global="simpleValue" type="java.lang.Integer"/>
...
</Context>
Transaction
从前面给出的 体系结构图 中可以看出,Transaction特性在GlobalNamingResources和Context中都有支持。
通过在JNDI中查询java:comp/UserTransaction可以得到UserTransaction的引用。