本文分为三部分,分别为:
- Tomcat文件系统
- Tomcat的主要组成部分
- Tomcat各组成部分之间的关系以及它们如何协作,构成一个系统
1。Tomcat文件系统
Tocmat6的结构与之前的结构有很大不同,文件目录都不一样。我个人感觉与之前的版本相比,Tomcat6的结构更清晰简洁,也更容易理解一些。改变的原因据说所为了解决一些由文件系统结构带来的问题,详细的内容我也不清楚。不过由此可以看出,系统的目录结构一定要认真设计,因为以后更改起来会很麻烦,可能会造成一些兼容性的问题。
下面这张图就算tomcat的目录结构:
CATALINA_HOME指的是tomcat的安装目录,如C:/Program Files/Apache Tomcat Group/Tomcat6.0
bin目录:这个目录里文件的主要作用所控制tomcat的启动与关闭(使用catalina或startup脚本),以及与启动关闭有关的安全管理(uli)等。archive版(解压缩后直接用的那种)的比使用安装包安装的那种要多一些sh和bat脚本。startup脚本实质上也是在调用catalina脚本,只不过所让它在后台运行。这里面也有一些jar包,包括bootstrap.jar, commons-daemon.jar, tomcat-juli.jar。还包括一些exe文件,是用来在windows平台安装服务用的。
conf目录:这个目录所我们与Tomcat打交道最多的一个目录。里面主要所配置文件,当tomcat启动时,就按照这里面的配置创建一些对象(组成worker,我认为)。里面的文件及简单描述如下:
- catalina.policy:包含Java Security Manager使用的安全策略描述。它替代了java自身所带的java.policy文件。这个文件的主要作用是防止jsp代码等用户代码破坏Tomcat容器,如system.exit(0)。只用在使用命令行启动tomcat并使用-security参数时,这个文件才被使用。
- catalina.properties:里面包含了不能被jsp或servlet修改的jar文件列表,如java.* org和tomcat.apache.*等。
- context.xml:顾名思义,这是有关context的配置文件。由于这个context.xml位于顶层,所以是一个被所有Web应用程序使用的配置文件。默认内容为web.xml文件的位置。
- logging.properties:默认为JULI logger使用的配置文件。
- server.xml:Tomcat中最主要的配置文件,定义了tomcat的体系结构。这个文件是被digester用来在tomcat启动时构建tomcat容器的配置文件。
- tocmat-users.xml:有关Tocmat管理员身份的配置文件,它是同server.xml中的UserDatabase Realm一起使用的。
- web.xml:这个默认的web.xml被Tomcat下所有的应用程序所使用。主要包括<servlet-mapping>, <servlet>标签,<mime-type>标签和<welcome-file-list>标签。
- 自动生成的用户应用程序的配置文件。当用户在Tomcat中部署一个应用时,tomcat会自动在这个文件夹里生成一个与应用程序中的contex.xml等价的文件。这个文件一般所放在一个目录中,目录结构如下:[servlet引擎名(catalina)]/[host name(localhost)]/[context path name(PetStore)].xml。此外,用户还可以创建一个[servlet 引擎名]/[主机名]/context.xml.default来创建某个引擎-主机组合下的默认配置文件。
lib目录:里面包含了Tomcat容器使用的所有jar包。这里也是用户存放多个web应用程序共享的jar包以及JDBC连接包的地方。
log目录:里面包含有tomcat生成的日志文件。这些日志文件默认是由JULI生成的,日志文件是按天为单位生成的。
temp目录:顾名思义,这个文件夹所Tomcat用来存放临时文件用的。
webapps目录:这是默认的web应用程序存放的位置。如果将war包放到这个目录下,tomcat会自动将这个war包解压;如果这个war文件被删除,解压后生成的文件夹也会被自动删除。
work目录:工作目录。这里是tomcat将jsp文件转换为Java servlet的地方,里面文件的目录结构一般所这样的:[引擎名]/[主机名]/web应用程序
从上面这些目录结构可以猜想的到,servlet引擎是Tomcat与web应用程序的一个重要界限,也算tomcat的核心所在。
2。Tomcat体系结构概览
在Tocmat4以后,tomcat的体系机构发生了很大的变化。Tomcat4以后的版本没有再基于以前的版本进行改进,而是彻底的重写。下面这张Tomcat示意图比较好地反映了一个经典的tomcat6的体系结构。值得注意的是,这张图里的有些部分并不是tomcat必须的。例如,在有其他的web server(如apache http server)来实现解译用户request并传给web应用程序的时候,Engine和Host可以被其他的web server替代。
在上面这张图中,有些组件只能有一个,使用灰色背景表示,在这张图里有Server,Engine和Context;有些可以有多个,使用白色背景表示,此图中有Service, Connector, Logger, Valve, Realm, Host, Wapper。
tomcat体系结构各组成部分的简介
The Server
The Server就是Tomcat自身,一个Tomcat程序实例(instance)。它的一个重要属性就是关闭Tomcat的端口号。“在一个给定的JVM中,只能创建一个Tomcat实例。“这句话是我从《Apache Tomcat6》这本书中看到的,但不是很理解。目前我的理解是这样,
The Server对象是Server接口的一个实现,一般常用的是StandardServer类的一个对象。
The Service
一个Server可以有多个Service,一般一个Server只有一个Service。一个Service包括一个Engine和多个Connector。
An Engine is a request-processing component that represents the Catalina Servlet engine. It examines
the HTTP headers to determine the virtual host or context to which requests should be passed.
上面这段话翻译过来大概是这样:
一个引擎是一个处理请求的组件,也就是Catalina Servlet引擎。它通过http request请求头的信息来向相应的virtual host或context转发request。
由此可见,这里的Engine是一个概念,而不是某个具体的文件,凡是符合一定标准的组件都可以作为引擎。
每一个Service都是由一组Connector(处理服务器与客户端之间交互的组件)与一个引擎组成的。引擎的作用是接受Connector传过来的request并将他们转发给相应的host。
Tomcat中的service一般是实现了service接口的一个StandardService类的对象。
The Connectors
Connector是用户请求到达服务器的第一站。每个connector都有一个端口号,常用的Connector有两种,一种是HTTP Connector,另一种是AJP Connector,除此之外,还有一些其他类型的接口。如果要使用SSL,在配置文件里修改的也是Connector属性。
The Engine
我觉得这是tomcat中最重要的部分,虽然它并不是不可或缺的。Engine除了前面所说的处理并转发request功能外,还可以提供java servlet服务。正是Engine实现了jsp到java文件的转换。
The Realm
Engine中的realm负责用户验证和授权。在一个web应用程序中,管理员会创建一些有不同权限的roles,实现这个机制的正是Realm。Realm可以管理的文件包括文本文件,数据库表格,LDAP 服务器等。
在不同的级别上都可以设置Realm,如Engine中的Realm就是顶层容器级的Realm,而各个Host,Context也可以有自己的Realm。
The valves
Valve是用来预处理用户请求的,有些类似于servlet中的filter。
The Logger
顾名思义,Logger是用来生成日志文件的。Engine级别的Logger 适用于全局,除非被某个host或context级别的logger所覆盖。
The Host
Host在功能上与apache中的 virtual host类似,在Apache中virtual host用来实现在一台机器上安装多个apache server,用他们的ip地址或主机名来区分。在tomcat中,多个Host是通过主机名来区分的,如www.examle.com与www.example.net就可以被区分。
Host是Engine的一个成员,在一个Engine中,可以有1个或多个host,包括一个默认的host和0个或多个虚拟的host。当engine无法确定将请求发给哪一个host时,就会将这个请求发给默认的那个host。
The Context
每个Context对应一个web应用程序,一个web应用程序的配置包括通知Engine/Host web应用程序的位置(root folder,还可以设置是否在发生改变时是否自动重载。不过自动重载会降低系统性能,因此建议仅在调试时使用这个选项。
还可以在Conetxt中设置errorpage,方便管理员检查错误。默认情况下Context是实现Context接口的一个Standard类的Context对象。
在启动时还可以设置Context的参数,增加用户验证。每个Context也是一个容器,里面可以有0个或多个servlet,Context将其作为StandardWrapper对象加载进来。
Tomcat体系结构中其他的组成部分
Tomcat中还定义了几个分别表示request,response和session的类,这几个类用来模拟客户端和服务器。
Connector体系结构
connector一般可以分为两类,一类是Http Connector,另一类是AJP Connector。Connector主要由两部分来实现,一部分在Apache端,一般是一个C写成的Apache模块,目前使用比较多的有mod_jk和mod_proxy两种。另一部分在Tomcat端,是用java写成的。org.apache.catalina.Connector类。这个类的构造函数接受一个参数,这个参数有两种选择,一个为Http/1.1,另一个是AJP/1.3。
生命周期(Lifecycle)
Lifecycle interface
Tomcat使用的一种“插件式(plugable)”的结构,管理这些插件的生命周期(何时启动与关闭)。当用户启动tomcat时,tomcat中的那些插件也会一起启动,当关闭时也是同样。这种多米诺效应是通过Lifecycle接口:LifecycleEvent和LifecycleListener 实现的。下面是Lifecycle接口的代码:
- public interface Lifecycle {
- public static final String INIT_EVENT = “init”;
- public static final String START_EVENT = “start”;
- public static final String BEFORE_START_EVENT = “before_start”;
- public static final String AFTER_START_EVENT = “after_start”;
- public static final String STOP_EVENT = “stop”;
- public static final String BEFORE_STOP_EVENT = “before_stop”;
- public static final String AFTER_STOP_EVENT = “after_stop”;
- public static final String DESTROY_EVENT = “destroy”;
- public static final String PERIODIC_EVENT = “periodic”;
- public void addLifecycleListener(LifecycleListener listener);
- public LifecycleListener[] findLifecycleListeners();
- public void removeLifecycleListener(LifecycleListener listener);
- public void start() throws LifecycleException;
- public void stop() throws LifecycleException;
- }
几乎所有的Tomcat组件都实现了Lifecycle接口,主要的控制组件都有LifecycleSuport对象,它们使用这个对象来管理其中的所有子Lifecycle对象。使用LifecycleSupport对象,当顶层对象调用start()方法时,它就会调用它的子组件的start()方法,子组件的子组件又会调用start()方法,就这样形成了多米诺效应。关闭时亦然。
LifecycleListener Interface
LifecycleListener接口可以被添加到任何层次的Tomcat容器 (Server, Service, Engine, Host, or Context),在Server这个级别,默认的Listener有三个。用户可以定义自己的Listener,不过需要将其在server.xml或context.xml中添加配置。用户自定义的Listener需要继承LifecycleListene接口。下面是LifecycleListner的代码和一个用户自定义Listener的一个示例:
- public interface LifecycleListener {
- public void lifecycleEvent(LifecycleEvent event);
- }
lifecycleEvent()接收一个LifecycleEvent类型的对象,这个对象包含事件类型和其他的附加信息。下面是一个示例:
- public MyListener implements LifecycleListener {
- public void lifecycleEvent(LifecycleEvent event){
- if (Lifecycle.START_EVENT.equals(event.getType())){
- //Code here to email that a Start Event was received
- }
- if (Lifecycle.STOP_EVENT.equals(event.getType())){
- //Code here to email that a Stop Event was received
- }
- }
再说Server.xml
在Tomcat中处于核心地位的文件应该就是这个了。当Tomcat启动时,Apache Commons Digester就会读取这份配置文件。Digester是用来读取xml文件并根据文件来生成java对象的一种对象。
- <Server port=”8005” shutdown=”SHUTDOWN”>
- <Listener className=”org.apache.catalina.core.AprLifecycleListener”
- SSLEngine=”on” />
- <Listener className=”org.apache.catalina.core.JasperListener” />
- <Listener className=”org.apache.catalina.mbeans.ServerLifecycleListener” />
- <Listener className=”org.apache.catalina.mbeans.
- GlobalResourcesLifecycleListener” />
- <Service name=”Catalina”>
- <Connector port=”8080” protocol=”HTTP/1.1”
- maxThreads=”150” connectionTimeout=”20000”
- redirectPort=”8443” />
- <Connector port=”8009” protocol=”AJP/1.3” redirectPort=”8443” />
- <Engine name=”Catalina” defaultHost=”localhost”>
- <Realm className=”org.apache.catalina.realm.UserDatabaseRealm”
- resourceName=”UserDatabase”/>
- <Host name=”localhost” appBase=”webapps”
- unpackWARs=”true” autoDeploy=”true”
- xmlValidation=”false” xmlNamespaceAware=”false”/>
- </Engine>
- </Service>
- </Server>
XML结构的本质是嵌套式的机构,Tomcat的开发者们决定使Tomcat自身也按这种结构设计。从这份示例server.xml文档也可以看出,Tomcat的结构和XML的结构是多么的一致。因此,要想弄清楚Tomcat的结构,最快捷的方法就是阅读配置文件。(server.xml&context.xml)。