本文分为三部分,分别为:
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,我认为)。里面的文件及简单描述如下:
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的核心所在。
在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。
The Server就是Tomcat自身,一个Tomcat程序实例(instance)。它的一个重要属性就是关闭Tomcat的端口号。“在一个给定的JVM中,只能创建一个Tomcat实例。“这句话是我从《Apache Tomcat6》这本书中看到的,但不是很理解。目前我的理解是这样,
The Server对象是Server接口的一个实现,一般常用的是StandardServer类的一个对象。
一个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类的对象。
Connector是用户请求到达服务器的第一站。每个connector都有一个端口号,常用的Connector有两种,一种是HTTP Connector,另一种是AJP Connector,除此之外,还有一些其他类型的接口。如果要使用SSL,在配置文件里修改的也是Connector属性。
我觉得这是tomcat中最重要的部分,虽然它并不是不可或缺的。Engine除了前面所说的处理并转发request功能外,还可以提供java servlet服务。正是Engine实现了jsp到java文件的转换。
Engine中的realm负责用户验证和授权。在一个web应用程序中,管理员会创建一些有不同权限的roles,实现这个机制的正是Realm。Realm可以管理的文件包括文本文件,数据库表格,LDAP 服务器等。
在不同的级别上都可以设置Realm,如Engine中的Realm就是顶层容器级的Realm,而各个Host,Context也可以有自己的Realm。
Valve是用来预处理用户请求的,有些类似于servlet中的filter。
顾名思义,Logger是用来生成日志文件的。Engine级别的Logger 适用于全局,除非被某个host或context级别的logger所覆盖。
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。
每个Context对应一个web应用程序,一个web应用程序的配置包括通知Engine/Host web应用程序的位置(root folder,还可以设置是否在发生改变时是否自动重载。不过自动重载会降低系统性能,因此建议仅在调试时使用这个选项。
还可以在Conetxt中设置errorpage,方便管理员检查错误。默认情况下Context是实现Context接口的一个Standard类的Context对象。
在启动时还可以设置Context的参数,增加用户验证。每个Context也是一个容器,里面可以有0个或多个servlet,Context将其作为StandardWrapper对象加载进来。
Tomcat中还定义了几个分别表示request,response和session的类,这几个类用来模拟客户端和服务器。
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。
Tomcat使用的一种“插件式(plugable)”的结构,管理这些插件的生命周期(何时启动与关闭)。当用户启动tomcat时,tomcat中的那些插件也会一起启动,当关闭时也是同样。这种多米诺效应是通过Lifecycle接口:LifecycleEvent和LifecycleListener 实现的。下面是Lifecycle接口的代码:
几乎所有的Tomcat组件都实现了Lifecycle接口,主要的控制组件都有LifecycleSuport对象,它们使用这个对象来管理其中的所有子Lifecycle对象。使用LifecycleSupport对象,当顶层对象调用start()方法时,它就会调用它的子组件的start()方法,子组件的子组件又会调用start()方法,就这样形成了多米诺效应。关闭时亦然。
LifecycleListener接口可以被添加到任何层次的Tomcat容器 (Server, Service, Engine, Host, or Context),在Server这个级别,默认的Listener有三个。用户可以定义自己的Listener,不过需要将其在server.xml或context.xml中添加配置。用户自定义的Listener需要继承LifecycleListene接口。下面是LifecycleListner的代码和一个用户自定义Listener的一个示例:
lifecycleEvent()接收一个LifecycleEvent类型的对象,这个对象包含事件类型和其他的附加信息。下面是一个示例:
在Tomcat中处于核心地位的文件应该就是这个了。当Tomcat启动时,Apache Commons Digester就会读取这份配置文件。Digester是用来读取xml文件并根据文件来生成java对象的一种对象。
XML结构的本质是嵌套式的机构,Tomcat的开发者们决定使Tomcat自身也按这种结构设计。从这份示例server.xml文档也可以看出,Tomcat的结构和XML的结构是多么的一致。因此,要想弄清楚Tomcat的结构,最快捷的方法就是阅读配置文件。(server.xml&context.xml)。