图解Tomcat体系结构

转自:http://blog.csdn.net/hhyatt/article/details/6287982

和:http://panlianghui-126-com.iteye.com/blog/810056

这是我的一篇老文,现在放到这里 :P

Apache Tomcat 是一款非常著名的开源 Servlet/JSP 容器。

Apache Tomcat 是一款非常著名的开源 Servlet/JSP 容器,被用做 Java Servlet 和 JavaServer Pages 技术的官方参考实现。如果您要了解这两种技术的细节可以查阅参考资料

让我们先来浏览一下 Tomcat 体系结构中的六个主要概念:

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中可以含有一个或多个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负责接收和处理来自它所属的Service中的所有Connector的请求。

Engine支持backgroundProcessorDelay、className、defaultHost、jvmRoute和name五个公共属性,而标准实现org.apache.catalina.core.StandardEngine还可能支持一些扩展属性。详细的内容您可以查阅这里

您可以通过稍后给出的 体系结构图 了解在整个Tomcat体系结构中Engine所处的位置。

从图中可以看出Engine右边有四个不同颜色的小方块,它们表示Engine所支持的四个不同的特性。相同颜色的小方块可能也会出现在其它的地方,这表示在那里也支持相同的或相似的特性。每种特性的具体描述可以在文中的Special Features中找到。

从图中可以看出Engine下边有一个红色的圆角矩形,它们表示Engine所支持的一个内嵌组件。相同颜色的圆角矩形可能也会出现在其它的地方,这表示在那里也支持相同的或相似的内嵌组件。每种内嵌组件的具体描述可以在文中的Nested Components中找到。

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负责接收来自客户端(Client)的请求。比较常见的两个是HTTP ConnectorAJP Connector

您可以通过稍后给出的 体系结构图 了解在整个Tomcat体系结构中Connector所处的位置。

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中找到。

Tomcat 的体系结构图

Tomcat体系结构图

GlobalNamingResources 组件为 Server 定义全局 JNDI 资源。这些资源出现在 Server 的全局 JNDI 资源上下文中。这个上下文和每个 web 应用程序的 JNDI 上下文不同。在全局 JNDI 上下文中定义的资源在每个 web 应用程序的 JNDI 上下文中不可见,但是可以通过 Resource Links 来改变这种可见性。如果您要了解在 Tomcat 中如何使用 JNDI 资源可以查阅参考资料

从前面给出的 体系结构图 中可以看出GlobalNamingResources右边有四个不同颜色的小方块,它们表示GlobalNamingResources所支持的四个不同的特性。相同颜色的小方块可能也会出现在其它的地方,这表示在那里也支持相同的或相似的特性。每种特性的具体描述可以在文中的Special Features中找到。

从前面给出的 体系结构图 中可以看出,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的更多信息,可以查阅这里

如果您要了解这些Realm的更多的设置信息,可以查阅参考资料

从前面给出的 体系结构图 中可以看出,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组件只在Context中有支持。

Manager是session管理器(session manager),负责session的创建和维护。

Manager元素应该嵌入到Context元素中,如果没有设置那么会自动创建一个默认的Manager。

Manager支持className和distributable两个公共属性,而标准实现org.apache.catalina.session.StandardManager和org.apache.catalina.session.PersistentManager还可能支持一些扩展属性。详细的内容您可以查阅这里

从前面给出的 体系结构图 中可以看出,Resources组件只在Context中有支持。

Resources表示web应用程序的静态资源。这使得我们有可能实现non-filesystem based Resources。如果想更深入的了解可以查阅参考资料

Resources元素应该嵌入到Context元素中,如果没有设置那么会自动创建一个默认的基于文件系统的Resources。

Resources支持className一个公共属性,而标准实现org.apache.naming.resources.FileDirContext还可能支持一些扩展属性。详细的内容您可以查阅这里

从前面给出的 体系结构图 中可以看出,WatchedResource组件只在Context中都有支持。

WatchedResource用来告知Auto Deployer那些静态资源的更新需要被监控。如果被监控的资源被更新了那么该资源所对应的web应用将会被重新装载。这个元素的内容必须是一个String。

从前面给出的 体系结构图 中可以看出,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特性在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特性在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特性在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特性只在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中都有支持。

在一些时候,网络管理员会将多个网络名(在DNS服务器中)解析到同一个服务器。通常每一个网络名会对应到一个Host。不过有时候需要将多个网络名对应到一个Host,Host Name Aliases用来完成这个目标。

一般的配置方法是在conf/server.xml文件的相关元素中加入:

<Host name="www.mycompany.com" ...>
  ...
  <Alias>mycompany.com</Alias>
  ...
</Host>

<Host>元素中可以嵌入一个或多个<Alias>元素。

从前面给出的 体系结构图 中可以看出,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特性只在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特性只在Context中都有支持。

如果使用标准的Context实现,当Catalina启动或Web应用装载时,会按如下的步骤自动进行设置:

  • 如果没有指定Loader元素,那么一个标准的Loader将会被设置
  • 如果没有指定Manager元素,那么一个标准的Manager将会被设置
  • 如果没有指定Resources元素,那么一个标准的Resources将会被设置
  • 处理conf/web.xml文件
  • 处理/WEB-INF/web.xml文件
  • 如果设置了security constraints,那么一个对应的Authenticator会被创建

从前面给出的 体系结构图 中可以看出,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特性在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特性在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特性在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特性在GlobalNamingResources和Context中都有支持。

通过在JNDI中查询Java:comp/UserTransaction可以得到UserTransaction的引用。

Tomcat是一个基于组件的服务器,它的构成组件都是可配置的,其中最外层的组件是Catalina Servlet容器,其它的组件按照一定的格式要求配置在这个容器中

    Tomcat各组件是在<Tomcat_HOME>\conf\server.xml文件中配置,其配置文件内容如下

   

Java代码   收藏代码
  1. <Server port="8005" shutdown="SHUTDOWN">  
  2.   
  3.     <Service name="Catalina">  
  4.     
  5.     <!--The connectors can use a shared executor, you can define one or more named thread pools-->  
  6.     <!--  
  7.     <Executor name="tomcatThreadPool" namePrefix="catalina-exec-"   
  8.         maxThreads="150" minSpareThreads="4"/>  
  9.     -->  
  10.       
  11.       
  12.     <!-- A "Connector" represents an endpoint by which requests are received  
  13.          and responses are returned. Documentation at :  
  14.          Java HTTP Connector: /docs/config/http.html (blocking & non-blocking)  
  15.          Java AJP  Connector: /docs/config/ajp.html  
  16.          APR (HTTP/AJP) Connector: /docs/apr.html  
  17.          Define a non-SSL HTTP/1.1 Connector on port 8080  
  18.     -->  
  19.     <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>  
  20.     <!-- A "Connector" using the shared thread pool-->  
  21.     <!--  
  22.     <Connector executor="tomcatThreadPool"  
  23.                port="8080" protocol="HTTP/1.1"   
  24.                connectionTimeout="20000"   
  25.                redirectPort="8443" />  
  26.     -->             
  27.     <!-- Define a SSL HTTP/1.1 Connector on port 8443  
  28.          This connector uses the JSSE configuration, when using APR, the   
  29.          connector should be using the OpenSSL style configuration  
  30.          described in the APR documentation -->  
  31.     <!--  
  32.     <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"  
  33.                maxThreads="150" scheme="https" secure="true"  
  34.                clientAuth="false" sslProtocol="TLS" />  
  35.     -->  
  36.   
  37.     <!-- Define an AJP 1.3 Connector on port 8009 -->  
  38.     <Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/>  
  39.   
  40.   
  41.     <!-- An Engine represents the entry point (within Catalina) that processes  
  42.          every request.  The Engine implementation for Tomcat stand alone  
  43.          analyzes the HTTP headers included with the request, and passes them  
  44.          on to the appropriate Host (virtual host).  
  45.          Documentation at /docs/config/engine.html -->  
  46.   
  47.     <!-- You should set jvmRoute to support load-balancing via AJP ie :  
  48.     <Engine name="Catalina" defaultHost="localhost" jvmRoute="jvm1">           
  49.     -->   
  50.     <Engine defaultHost="localhost" name="Catalina">  
  51.   
  52.       <!--For clustering, please take a look at documentation at:  
  53.           /docs/cluster-howto.html  (simple how to)  
  54.           /docs/config/cluster.html (reference documentation) -->  
  55.       <!--  
  56.       <Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster"/>  
  57.       -->          
  58.   
  59.       <!-- The request dumper valve dumps useful debugging information about  
  60.            the request and response data received and sent by Tomcat.  
  61.            Documentation at: /docs/config/valve.html -->  
  62.       <!--  
  63.       <Valve className="org.apache.catalina.valves.RequestDumperValve"/>  
  64.       -->  
  65.   
  66.       <!-- This Realm uses the UserDatabase configured in the global JNDI  
  67.            resources under the key "UserDatabase".  Any edits  
  68.            that are performed against this UserDatabase are immediately  
  69.            available for use by the Realm.  -->  
  70.       <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>  
  71.   
  72.       <!-- Define the default virtual host  
  73.            Note: XML Schema validation will not work with Xerces 2.2.  
  74.        -->  
  75.       <Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true" xmlNamespaceAware="false" xmlValidation="false">  
  76.   
  77.         <!-- SingleSignOn valve, share authentication between web applications  
  78.              Documentation at: /docs/config/valve.html -->  
  79.         <!--  
  80.         <Valve className="org.apache.catalina.authenticator.SingleSignOn" />  
  81.         -->  
  82.   
  83.         <!-- Access log processes all example.  
  84.              Documentation at: /docs/config/valve.html -->  
  85.         <!--  
  86.         <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"    
  87.                prefix="localhost_access_log." suffix=".txt" pattern="common" resolveHosts="false"/>  
  88.         -->  
  89.   
  90.       <Context docBase="TestTomcat" path="/TestTomcat" reloadable="true" source="org.eclipse.jst.j2ee.server:TestTomcat"/><Context docBase="xishuizhipanBlog" path="/xishuizhipanBlog" reloadable="true" source="org.eclipse.jst.jee.server:xishuizhipanBlog"/></Host>  
  91.     </Engine>  
  92.   </Service>  
  93. </Server>  

   server.xm文件的基本结构如下:

  

       <Server> 代表了整个Catalina Servlet 容器,它是Tomcat实例的顶层元素。可包含一个或多个<Service>元素

       <Service>包含一个<Engine>元素,以及一个或多个<Connector>元素,这些<Connector>元素共享同一个<Engine>元素

       <Connector>代表和客户程序实际交互的组件,它负责接收客户请求,以及返回客户响应结果。

        <Engine>每个<Service>元素只能包含一个<Engine>元素.  <Engine>元素处理在同一个<Service>中所有<Connector>元素接收到的客户请求.

        <Host>一个<Engine>元素中可以包含多个<Host>元素.每个<Host>元素定义了一个虚拟主机,它可以包含一个或多个Web应用.

        <Contex>每个<Context>元素代表了运行虚拟主机上的但个Web应用.一个<Host>元素中可以包含多个<Context>元素.
        组件的关系图如下

            

 

 下面,介绍Tomcat的基本元素

 1.配置Server元素

    Server>元素代表了整个Catalina  Servler容器,它是Tomcat实例的顶层元素,由org.apache.catalina.Server接口来定义.<Server>元素中可以包含一个或者多个<Service>元素,但<Server>元素不能作为任何其他元素的子元素.

  

Java代码   收藏代码
  1. <Server port="8005" shutdown="SHUTDOWN">  

    className    :指定实现org.apache.catalina.Server接口的类,默认值为org.apache.catalina.core.StandardServer.
       port              :指定Tomcat服务器监听shutdown命令的端口.终止Tomcat服务运行时,必须在Tomcat服务器所在的机器上发出Shutdown命令.该属性是必须设定的.
       shutdown      :指定终止Tomcat服务器运行时,发给Tomcat服务器的shutdown监听端口的字符串.该属性是必须设定的.

  2.配置Service元素

    <Service>元素由org.apache.catalina.Service接口定义,它把韩一个<Engine>元素,以及一个或多个<Connector>元素,这些<Connector>元素共享一个<Engine>元素.  

   

Java代码   收藏代码
  1. <Service name="Catalina">  

   <Service>处理所有直接由Tomcat服务器接收的Web客户请求。

  className    :指定实现org.apache.catalina.Service接口的类,默认值org.apache.catalina.core.StandardService.
    name              :定义Service的名字.

 3.配置Engine元素

    <Engine>元素由org.apahe.catalina.Engine接口定义.  每个<Service>元素只能包括一个<Engine>元素.  <Engine>元素处理在同一个<Service>中所有<Connector>元素接收到的客户请求.

  

Java代码   收藏代码
  1. <Engine defaultHost="localhost" name="Catalina">  

 className    :指定实现org.apache.catalina.Engine接口的类,默认值为org.apache.catalina.core.StandardEngine.
       name              :定义Engine的名字.
在<Engine>元素中可以包含如下的子元素:
               <Logger>
               <Realm>
               <Valve>
               <Host>
4.配置Connector元素

  <Connector>元素由org.apache.catalina.Connector接口定义.<Connector>元素代表与客户程序实际交互的组件,它负责接收客户的请求,以及向客户返回响应结果。

 

Java代码   收藏代码
  1. <Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="8443"/>  

  

Java代码   收藏代码
  1. <Connector port="8009" protocol="AJP/1.3" redirectPort="8443"/>  

  第一个<Connector>元素定义了一个HTTP  Connector,它通过8080端口接收HTTP请求;
   第二个<Connector>元素定义了一个JK  Connector,它通过8009端口接收由其他HTTP服务器(如Apache服务器)转发过来的客户请求.
   <Connector>属性含义(共同属性):

--------------------------------------------------------------
       className            :指定实现org.apache.catalina.Connector  接口的类,默认值为org.apache.catalina.core.StandardConnector.
       enableLookups    :如果设为true,表示支持域名解析,可以把IP地址解析为主机名.Web应用调用request.getRemostHost方法将返回客户的主机名.该属性默认值为true.
       redirectPort      :指定转发端口.如果当前端口只支持non-SSL请求,在需要安全通信的场合,将把客户请求转发到基于SSL的redirectPort的端口.
 HttpConnector的属性描述如下:
--------------------------------------------------------------
       calssName            :指定实现org.apache.catalina.Connector接口的类,默认值为org.apache.coyote.tomcat5.CoyoteConnector.
       enableLookups    :同上.
       redirectPort      :同上.
       prot                      :设定TCP/IP断口号,默认为8080.
       address                :如果服务器有两个以上IP地址,该属性可以设定端口监听的IP地址,默认情况下,端口会监听服务器上所有IP地址.
       bufferSize          :设定由端口创建的输入流的缓存大小,默认值为2048byte.
       protocol              :设定HTTP协议,默认值为HTTP/1.1.
       maxThreads          :设定处理客户请求的线程的最大数目,这个值也决定了服务器可以同时响应客户请求的最大数目,默认值为200.
       acceptCount        :设定在监听端口队列中的最大客户请求数,默认值为10.  如果队列已满,客户请求将被拒绝.
       connectionTimeout  :定义建立客户连接超时的时间,以毫秒为单位.如果设置为-1,表示不限制建立客户连接的时间.

       JK  Connector  的属性如下:
--------------------------------------------------------------
       className            :指定实现org.apache.catalina.Connector接口的类,默认值为org.apache.coyote.tomact5.CoyoteCnnector.
       enableLookups    :同上.
       redirectPort      :同上.
       port                      :设定AJP端口号.
       protocol              :必须设定为AJP/1.3协议.

5.配置<Host>元素

  <Host>元素由org.apache.catalina.Host接口定义.一个<Engine>元素可以包含多个<Host>元素.每个<Host>元素定义了一个虚拟主机,它可以包含一个或多个Web应用.  

 

Java代码   收藏代码
  1. <Host appBase="webapps" autoDeploy="true" name="localhost" unpackWARs="true" xmlNamespaceAware="false" xmlValidation="false">  

  以上代码定义了一个名为localhost的虚拟主机,Web客户访问它的URL为:  http://localhost:8080/
  className        :指定实现org.apache.catalina.Host接口的类,默认值为org.apache.catalina.core.StandardHost.
       appBase            :指定虚拟主机的目录,可以指定绝对目录,也可以指定相对于<CATALINA_HOME>的相对目录.  如果此项没有设定,默认值为<CATALINA_HOME>/webapps.
       unpackWARs      :如果此项设为true,表示将把Web应用的WAR文件先展开为开放目录结构后再运行.如果设为false,将直接运行WAR文件.
       autoDeploy      :如果此项设为true,表示当Tomcat服务器处于运行状态时,能够监测appBase下的文件,如果有新的Web应用加入进来,会自动发布这个Web应用.
       alias                :指定虚拟主机的别名,可以指定多个别名.
       deployOnStartup  :如果此项设为true,表示Tomcat服务器启动时会自动发布appBase目录下的所有Web应用,如果Web应用在server.xml中没有相应的<Context>元素,将采用Tomcat默认的Context.  deployOnStartup的默认值为true.
       name                  :定义虚拟主机的名字.}
 在<Host>元素中可以包含如下的子元素:
               <Logger>
               <Realm>
               <Valve>
               <Context>
6.配置Contex元素

   <Context>元素由org.apache.catalina.Context接口定义.  <Context>元素是使用最频繁的元素.  每个<Context>元素代表了运行在虚拟主机上的单个Web应用.  一个<Host>元素中可以包含多个<Context>元素.

  

Java代码   收藏代码
  1. <Context docBase="TestTomcat" path="/TestTomcat" reloadable="true" source="org.eclipse.jst.j2ee.server:TestTomcat"/><Context docBase="xishuizhipanBlog" path="/xishuizhipanBlog" reloadable="true" source="org.eclipse.jst.jee.server:xishuizhipanBlog"/></Host>  

  
className      :指定实现org.apache.catalina.Context接口的类,默认值为org.apache.catalina.core.StandardContext.
       path                :指定访问该Web应用的URL入口.
       docBase          :指定Web应用的文件路径.可以给定绝对路径,也可以给定相对于Host的appBase属性的相对路径.  如果Web应用采用开放目录结构,那就指定Web应用的根目录;如果Web应用是个WAR文件,那就指定WAR文件的路径.
       reloadable    :如果这个属性设为true,Tomcat服务器在运行状态下会监视在WEB-INF/class和WEB-INF/lib目录下CLASS文件的改动.如果检测到有calss文件被更新,服务器会自动重新加载Web应用.
       cookies          :指定是否通过Cookie来支持Session,默认为true.
       useNaming      :指定是否支持JNDI,默认为true.

<----------------------------------------------------------------------------------------------------------------------------->

 

下面解说下tomcat的启动过程

 从开始学习网页编程时,我就一直在疑惑,为什么这个程序不要main函数,直接启动服务器就行了。但是服务器又是怎么启动的?

 最近看了一片文档,以及自己查看tomcat源码,才大概了解那么一点。

 1.启动tomcat

    apache-tomcat-6.0.29\bin\bootstrap.jar
    org.apache.catalina.startup.Bootstrap  start 
   Bootstrap
Tomcat的入口。比如启动、关闭、重启都是通过这个类实现对tomcat的控制。
2.ClassLoader的使用
Tomcat
对不同的模块可能使用不同的ClassLoader加载。这也就是为什么很多类不在启动的classpath中,却可以被它调用的原因。
下面是Bootstrap初始化ClassLoader的方法:

 

Java代码   收藏代码
  1. private void initClassLoaders() {  
  2.       try {  
  3.           commonLoader = createClassLoader("common"null);  
  4.           if( commonLoader == null ) {  
  5.               // no config file, default to this loader - we might be in a 'single' env.  
  6.               commonLoader=this.getClass().getClassLoader();  
  7.           }  
  8.           catalinaLoader = createClassLoader("server", commonLoader);  
  9.           sharedLoader = createClassLoader("shared", commonLoader);  
  10.       } catch (Throwable t) {  
  11.           log.error("Class loader creation threw exception", t);  
  12.           System.exit(1);  
  13.       }  
  14.   }  

 

 

 

 


   下图是Tomcat用户手册上看到的。
       Bootstrap
          |
       System
          |
       Common
      /      \
 Catalina   Shared
 (server)     /   \
      Webapp1  Webapp2 ...  
Bootstrap
JVM提供的
System
是在classpath中提供的
Common
包含配置文件/org/apache/catalina/startup/catalina.properties中指定的类库支持
Catalina
Shared都从Common中继承,包含的类库也在上面配置文件中指定。
WebappX
在部署单个Tomcat5实例时指定。一个webapp下面的类库对另外一个是不可见的
Tomcat
加载类的顺序和普通的不太一样,如下:
Bootstrap classes of your JVM
System class loader classses (described above)
/WEB-INF/classes of your web application
/WEB-INF/lib/*.jar of your web application
$CATALINA_HOME/common/classes
$CATALINA_HOME/common/endorsed/*.jar
$CATALINA_HOME/common/lib/*.jar
$CATALINA_BASE/shared/classes
$CATALINA_BASE/shared/lib/*.jar
注意,如果希望不使用JVM本身提供的类。这时可以使用jdkendorsed 特性

   3. Catalina类的作用

    如果要启动Tomcat,那么一个org.apache.catalina.startup.Catalina实例就生成,由它完成接下来的工作。

   下面是它启动的代码

Java代码   收藏代码
  1. public void start() {  
  2.   
  3.        if (getServer() == null) {  
  4.            load();  
  5.        }  
  6.   
  7.        if (getServer() == null) {  
  8.            log.fatal("Cannot start server. Server instance is not configured.");  
  9.            return;  
  10.        }  
  11.   
  12.        long t1 = System.nanoTime();  
  13.          
  14.        // Start the new server  
  15.        if (getServer() instanceof Lifecycle) {  
  16.            try {  
  17.                ((Lifecycle) getServer()).start();  
  18.            } catch (LifecycleException e) {  
  19.                log.error("Catalina.start: ", e);  
  20.            }  
  21.        }  
  22.   
  23.        long t2 = System.nanoTime();  
  24.        if(log.isInfoEnabled())  
  25.            log.info("Server startup in " + ((t2 - t1) / 1000000) + " ms");  
  26.   
  27.        try {  
  28.            // Register shutdown hook  
  29.            if (useShutdownHook) {  
  30.                if (shutdownHook == null) {  
  31.                    shutdownHook = new CatalinaShutdownHook();  
  32.                }  
  33.                Runtime.getRuntime().addShutdownHook(shutdownHook);  
  34.                  
  35.                // If JULI is being used, disable JULI's shutdown hook since  
  36.                // shutdown hooks run in parallel and log messages may be lost  
  37.                // if JULI's hook completes before the CatalinaShutdownHook()  
  38.                LogManager logManager = LogManager.getLogManager();  
  39.                if (logManager instanceof ClassLoaderLogManager) {  
  40.                    ((ClassLoaderLogManager) logManager).setUseShutdownHook(  
  41.                            false);  
  42.                }  
  43.            }  
  44.        } catch (Throwable t) {  
  45.            // This will fail on JDK 1.2. Ignoring, as Tomcat can run  
  46.            // fine without the shutdown hook.  
  47.        }  
  48.   
  49.        if (await) {  
  50.            await();  
  51.            stop();  
  52.        }  
  53.   
  54.    }  

 

 

  启动过程先载入配置文件,然后根据配置文件启动的Server实例启动实例 

 

 

 

 

 

 

  4. Server对象的生成

    服务的生成就是根据配置文件server.xml,实例化的对象。对象实例化过程中,会做载入webapp,在特定端口等待客户连接等工作。
server.xml到对象的映射是通过commons-digester.jar包完成的。这个包的一个主要功能就是映射xmljava对象。
catalina
类的方法createStartDigester完成了这个工作。部分代码如下

 

Java代码   收藏代码
  1.  protected Digester createStartDigester() {  
  2.         long t1=System.currentTimeMillis();  
  3.         // Initialize the digester  
  4.         Digester digester = new Digester();  
  5.         digester.setValidating(false);  
  6.         digester.setRulesValidation(true);  
  7.   
  8.      -------------  -------------   -------------  
  9.  digester.addObjectCreate("Server",  
  10.                                  "org.apache.catalina.core.StandardServer",  
  11.                                  "className");  
  12.         digester.addSetProperties("Server");  
  13.         digester.addSetNext("Server",  
  14.                             "setServer",  
  15.                             "org.apache.catalina.Server");  
  16.   ————————————————————————————  
  17.      // Add RuleSets for nested elements  
  18.         digester.addRuleSet(new NamingRuleSet("Server/GlobalNamingResources/"));  
  19.         digester.addRuleSet(new EngineRuleSet("Server/Service/"));  
  20.         digester.addRuleSet(new HostRuleSet("Server/Service/Engine/"));  
  21.         digester.addRuleSet(new ContextRuleSet("Server/Service/Engine/Host/"));  
  22.         digester.addRuleSet(ClusterRuleSetFactory.getClusterRuleSet("Server/Service/Engine/Host/Cluster/"));  
  23.         digester.addRuleSet(new NamingRuleSet("Server/Service/Engine/Host/Cont  
  24.   
  25.   
  26. ——————————————————  
  27. return (digester);  
  28. }  
Java代码   收藏代码
  1.   

     digester会在解析之后,返回一个对象。

  5. 服务的中止
org.apache.catalina.core.StandardServer.await
是保持tomcat运行的秘密。方法启动一个ServerSocket,侦听发出停止的字符串。这是一个死循环。当有停止运行的字符发出,跳出此循环。 

     

Java代码   收藏代码
  1. public void await() {  
  2.        // Negative values - don't wait on port - tomcat is embedded or we just don't like ports  
  3.        if( port == -2 ) {  
  4.            // undocumented yet - for embedding apps that are around, alive.  
  5.            return;  
  6.        }  
  7.        if( port==-1 ) {  
  8.            whiletrue ) {  
  9.                try {  
  10.                    Thread.sleep( 10000 );  
  11.                } catch( InterruptedException ex ) {  
  12.                }  
  13.                if( stopAwait ) return;  
  14.            }  
  15.        }  
  16.          
  17.        // Set up a server socket to wait on  
  18.        ServerSocket serverSocket = null;  
  19.        try {  
  20.            serverSocket =  
  21.                new ServerSocket(port, 1,  
  22.                                 InetAddress.getByName("localhost"));  
  23.        } catch (IOException e) {  
  24.            log.error("StandardServer.await: create[" + port  
  25.                               + "]: ", e);  
  26.            System.exit(1);  
  27.        }  
  28.   
  29.        // Loop waiting for a connection and a valid command  
  30.        while (true) {  
  31.   
  32.            // Wait for the next connection  
  33.            Socket socket = null;  
  34.            InputStream stream = null;  
  35.            try {  
  36.                socket = serverSocket.accept();  
  37.                socket.setSoTimeout(10 * 1000);  // Ten seconds  
  38.                stream = socket.getInputStream();  
  39.            } catch (AccessControlException ace) {  
  40.                log.warn("StandardServer.accept security exception: "  
  41.                                   + ace.getMessage(), ace);  
  42.                continue;  
  43.            } catch (IOException e) {  
  44.                log.error("StandardServer.await: accept: ", e);  
  45.                System.exit(1);  
  46.            }  
  47.   
  48.            // Read a set of characters from the socket  
  49.            StringBuffer command = new StringBuffer();  
  50.            int expected = 1024// Cut off to avoid DoS attack  
  51.            while (expected < shutdown.length()) {  
  52.                if (random == null)  
  53.                    random = new Random();  
  54.                expected += (random.nextInt() % 1024);  
  55.            }  
  56.            while (expected > 0) {  
  57.                int ch = -1;  
  58.                try {  
  59.                    ch = stream.read();  
  60.                } catch (IOException e) {  
  61.                    log.warn("StandardServer.await: read: ", e);  
  62.                    ch = -1;  
  63.                }  
  64.                if (ch < 32)  // Control character or EOF terminates loop  
  65.                    break;  
  66.                command.append((char) ch);  
  67.                expected--;  
  68.            }  
  69.   
  70.            // Close the socket now that we are done with it  
  71.            try {  
  72.                socket.close();  
  73.            } catch (IOException e) {  
  74.                ;  
  75.            }  
  76.   
  77.            // Match against our command string  
  78.            boolean match = command.toString().equals(shutdown);  
  79.            if (match) {  
  80.                break;  
  81.            } else  
  82.                log.warn("StandardServer.await: Invalid command '" +  
  83.                                   command.toString() + "' received");  
  84.   
  85.        }  
  86.   
  87.        // Close the server socket and return  
  88.        try {  
  89.            serverSocket.close();  
  90.        } catch (IOException e) {  
  91.            ;  
  92.        }  
  93.   
  94.    }  

  跳出循环后,系统执行关闭连接等资源的操作,服务就中止了。

Catalina.stopServer方法用于发出一个让服务停止的指令

Java代码   收藏代码
  1. Socket socket = new Socket(hostAddress, getServer().getPort());  
  2.                OutputStream stream = socket.getOutputStream();  
  3.                String shutdown = getServer().getShutdown();  
  4.                for (int i = 0; i < shutdown.length(); i++)  
  5.                    stream.write(shutdown.charAt(i));  
  6.                stream.flush();  
  7.                stream.close();  
  8.                socket.close();  

 


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值