本文是 Tomcat 工程部署委员会的数位成员合作完成,以下作者做出了最大的贡献。
l Craig R. McClanahan ( [email protected] )
以下章节包含如下信息:
l 概述:简要介绍并且加入其他信息的链接。
l 安装:描述如何获取并安装部署Tomcat 下web 应用程序的组件和方法。
l 部署组织:讨论web 应用程序标准的目录结构(在Servlet API 规范中定义),web 应用程序部署描述符以及将Tomcat 整合到你的部署环境中的可选配置。
l 源码组织:介绍一个组织您工程源码的有效方法,同时介绍使用Ant 管理编译的build.xml 文件。
l 部署过程:提供一个使用推荐方式进行部署的过程。
l 示例程序:目录提供一个根据上述原则进行构建的、简单但功能齐全的“Hello ,World ”程序。您可以使用这个程序进行学习和研究。
祝贺你!您决定使用 Tomcat 学习构建使用 servlet 和 JSP 页面的 web 应用程序。那,现在该做些什么呢?
本文主要概括了使用 Tomcat 建立一个部署环境,组织源码同时编译和测试应用程序的基本过程。不讨论 web 应用程序的架构或者最佳实践或深入使用开发工具的方法。关于源码以及其他信息包含在其他章节中。
本文介绍的方法适用于使用文本编辑器以及命令行工具开发并且调试应用程序的开发者。介绍具有一般性,但您可以很轻松的使用 Windows 或 Unix 平台下的开发工具进行开发。如果您使用 IDE 进行开发,需要根据开发环境的特点灵活运用本文中描述的方法。
在使用 Tomcat 进行 web 应用程序开发之前首先需要安装 Tomcat6.0 。安装步骤如下:
Tomcat6.0 运行在 JDK5.0 中。
在 http://tomcat.apache.org/download-60.cgi 可以下载到 Tomcat 服务器。本手册假定您使用最新发布的 Tomcat6.0 版本。下载和安装 Tomcat6.0 的详细信息请查看这里。
在手册的附录中,示例 shell 脚本假定您配置了 CATALINA_HOME 这个包含 Tomcat6.0 安装目录的环境变量。
在 http://ant.apache.org/bindownload.cgi 可以下载到 ant 工具。本文假定您使用 Ant1.4 及以后版本。本文中的所有配置应该和 Ant 后续版本兼容,但没有经过测试。
从上述地址下载并安装 ant ,然后将 ant 的 bin 目录加入 PATH 环境变量中。完成后,您就可以在命令行直接执行 ant 脚本了。
除了上述工具外,强烈建议您安装一个源码控制系统,比如说 CVS (用来保存源码历史版本的信息)。除了 CVS 服务器外,最好使用合适的客户端工具来 check out 或 check in 源码。可以在 http://www.cvshome.org 下载到很多版本的 CVS 服务器和客户端程序。
在介绍如何组织源码目录前,首先检查以下 web 应用程序的运行环境。在 Servlet API2.2 规范出现前,服务器平台很少有共性。但 2.2 版本(及以后)的服务器遵循规范,只接受标准格式的 web 应用程序压缩包( WAR 文件),在随后会有相关说明。
一个 web 应用程序是一组标准模式下任意组合的文件夹和文件集合。这种层次结构可以是未打包的(每一个目录和文件夹是文件系统中独立存在的)和打包的(所有文件和文件夹被压打包在一个 web 压缩文件中,叫 WAR 文件)两种形式。前一种适合开发时期使用,后一种适合在真实环境中使用。
您的 web 应用程序的最高层次的目录就是应用程序的根目录。您可以将包含引用程序用户接口的所有 HTML 文件和 JSP 文件放在这里。当系统管理员将您的应用程序部署在一个特殊的服务器中,他会给您应用程序的相对路径(下一节描述在 Tomcat 中手动部署应用程序的方法)。例如,如果系统管理员给您的相对路径是 /catalog ,请求 URL 为 /catalog/index.html 的将会取得您文件系统根目录的 index.html 文件。
为了方便的建立标准格式的 WAR 文件,可以方便的组织您 web 应用程序中的文件,请将文件组织为相同格式。可以在您 web 应用程序的目录下包含如下信息:
l *.html , *.jsp, 其他文件 :在您的应用程序中,需要包含 HTML 和 JSP 文件以及其他必须让浏览器访问的文件( JavaScript ,样式表文件和图片)。在一个大的应用程序中,您可能会将这些文件放到一个子文件夹中,但对于一个小程序,将它们保存在单一的文件夹中更简单。
l /WEB-INF/web.xml : WEB 应用程序部署描述符。这个 XML 文件描述了 servlet 和应用程序中的其他组件,以及一些初始化参数和您想让服务器执行的一些容器控制的安全配置。在以后的描述中,将介绍到这个文件的更详细的说明。
l /WEB-INF/classes/ :这个目录中包含应用程序需要的 java 类文件和其他资源,以及其他没有包含到 Jar 中的非 servlet 类文件。如果您的类使用 Java 包进行组织,在 /WEB-INF/classes 目录下使用相同包结构即可。例如:您有一个类叫做 com.mycompany.mypackage.MyServlet ,那么他应该被保存在 /WEB-INF/classes/com/mycompany/mypackage/ 目录下,名称是 MyServlet.class 。
l /WEB-INF/lib/ :这个目录中包含您应用程序中使用的所有 Jar 文件,例如第三方类库或 JDBC 驱动程序。
当您将应用程序安装到 Tomcat 或其他兼容 2.2 或 2.3 的服务器中时, WEB-INF/classes/ 目录下的类,以及 WEB-INF/lib/ 目录下 jar 包中的类文件在您的应用程序中可见。所以,如果您将所有需要的包放在这些地方,安装应用程序就会很容易,因为不需要调整系统路径,也不需要为服务器单独安装全局的库文件。
如果您需要更详细的介绍,可以查看 Servet API ( 2.3 版) 规范的第 9 章。
和大多数 servlet 容器一样, Tomcat 6.0 支持安装所有 web 应用程序中共享的 Jar 文件。 Tomcat 如何定位和共享文件的详细内容在 Class Loader HOW-TO 一节有更详细的说明,在这里只做简单说明。在 Tomcat6.0 中,以下两个位置可以保存用于共享的库文件:
l $CATALINA_HOME/common/lib :这个目录下的 Jar 文件可以被所有 web 应用程序和 Tomcat 内部流程共享。将供所有应用程序和 Tomcat 内部使用的 JDBC 驱动程序保存在这里是一个好主意。
l $CATALINA_BASE/shared/lib : 这个目录下的 Jar 文件可以被所有 web 应用程序共享,但 Tomcat 内部不能使用。这是保存所有应用程序的共享库文件的正确位置。
在 Tomcat 中预先安装了许多共享包,包括:
l Servlet2.4 和 JSP2.0 的 API ,这些文件是编写 servlet 和 JSP 的基础。
l 兼容 JAXP1.2 版本的 XML 解析器,您的应用程序可以执行基于 DOM 或 SAX 的 XML 解析。
以下描述中使用 $CATALINA_HOME 指代 Tomcat6.0 的安装目录,所有相对路径都以该路径为基础。如果您使用 CATALINA_BASE 变量配置 Tomcat6.0 的多个实例,应该使用 CATALINA_BASE 作为以下描述的根目录。
前文中已经说过, /WEB-INF/web.xml 文件包括应用程序的部署描述信息。文件的扩展名已经说明这个文件是一个 XML 文件,并且定义了服务器必须了解的有关应用程序的所有信息。
部署描述符的完整语法以及完整语意在 Servlet 2.3API 规范的第十三章有详细描述,现在,很多部署工具提供创建和编辑部署描述符的方式。同时,会提供基本的 web.xml 文件作为开始。这个文件包含所有元素的注释。
注意 : Servet 规范包含一个 web 应用程序部署描述符的 DTD 文件, tomcat6.0 在解析 web.xml 文件时引用定义在内部的规则。值得注意的是,您必须按照 DTD 中声明的顺序在 web.xml 文件中配置各种元素。
以下描述中使用 $CATALINA_HOME 指代 Tomcat6.0 的安装目录,所有相对路径都以该路径为基础。如果您使用 CATALINA_BASE 变量配置 Tomcat6.0 的多个实例,应该使用 CATALINA_BASE 作为以下描述的根目录。
/META-INF/context.xml 文件可以用来对 Tomcat 进行特殊配置,例如日志,数据源,事务控制配置等。文件必须包含一个 Context 元素,这个元素包含在 Host 元素中,描述 host 的一些配置。。
一个 web 应用程序必须部署在 servlet 容器才可以执行。在开发中也是这样。下文将会描述如何使用 Tomcat6.0 运行应用程序。一个 web 应用程序用以下方法质疑进行部署。
l 将未打包的子目录结果拷贝到 $CATALINA_HOME/webapps/ 目录下
Tomcat 使用子目录的名称作为应用程序的上下文。我们将使用 build.xml 文件进行部署,因为这时最快也是最容易的部署方式。安装或更新应用程序后,请重启 Tomcat 服务器。
l 将 web 应用程序压缩包拷贝到 $CATALINA_HOME/webapps/ 目录下
当 Tomcat 启动时,服务器自动将 web 应用程序压缩包解包执行。安装第三方提供的或其他团队提供的额外的应用程序时通查使用这种方式。
注意 :如果您使用这种方式并且希望议会更新应用程序,需要同时替换 WAR 文件和 Tomcat 解包的目录,然后重启服务器,这样修改才会生效。
l 使用 Tomcat6.0 来进行应用程序的部署和解除部署。
Tomcat6.0 包含一个 web 应用程序,这个应用程序默认部署在 /manager 路径下,当 Tomcat 运行时可以用他部署或解除部署应用程序。
l 在部署脚本中使用 ant 任务
Tomcat6.0 包含一些 ant 构建工具的自定义任务,这些任务可以自动执行部署命令。在 Tomcat 部署器中使用这些任务。
l 使用 Tomcat 部署工具
Tomcat6.0 提供一个绑定 ant 任务的打包工具,可以在应用程序部署到服务器前对 JSP 页面进行自动预编译。
将程序部署在其他的 servlet 容器的步骤可能不尽相同,只要你容器兼容 Servlet 2.2 API 规范,就可以接受 war 文件。注意:其他容器不一定可以部署未打包的目录结构,或共享库文件,但这些特性确实是经常用到的。
以下描述中使用 $CATALINA_HOME 指代 Tomcat6.0 的安装目录,所有相对路径都以该路径为基础。如果您使用 CATALINA_BASE 变量配置 Tomcat6.0 的多个实例,应该使用 CATALINA_BASE 作为以下描述的根目录。
本文建议开发者在开发过程中将源码文件的目录和可部署的目录完全分开。这样做有以下几点好处:
l 这样做,源码目录可以更好的管理,移动和备份。
l 可以在源码文件中更方便的使用源码控制工具。
l 如果部署目录结构很容易分离,这些文件可以很容易的制作成应用程序安装包。
马上您将会看到,使用 ant 开发工具来创建和执行程序是十分方便的。
您可以选择任何文件和目录结构来保存源代码。但以下介绍的方式是十分合适的并且 build.xml 文件可以识别。所有模块在您应用的程序工程源码目录下:
l docs/ :保存所有文档。
l src/ : Java 源码文件,包括 servlet , beans 和其他类。如果源码文件是按包的形式进行组织,包结构需要和目录结构一致。
l web/ : web 站点的静态内容( HTML 页面, JSP 页面, JavaScript 文件, CSS 样式表文件和图片)。这个目录是 web 应用程序的跟目录,其以下的子目录都可以使用相同方式在请求 URI 中访问。
l web/WEB-INF/ :应用程序的特殊配置文件,包括 web 应用程序部署描述符( Servlet 规范中定义的 web.xml 文件),自定义标签描述文件。即使这个目录是 web 根目录的子目录,但 Servlet 规范进制客户端对这个目录及其子目录进行直接访问。所以,这里是保存敏感资源的好地方(比如数据库的用户名和密码),但也需要您的应用程序不泄漏这些敏感信息。
在应用程序的部署过程中,会创建两个临时的文件夹:
l build/ :当执行缺省编译时,目录中的内容是 war 文件的精确映像。 Tomcat6.0 允许部署未打包的文件,部署可以通过将文件拷贝到 $CATALINA_HOME/webapps 目录下或使用“ Manager ”程序进行。后者在开发过程中十分有用,以后将会详细描述。
l dist/ :当您执行 ant 中的 dist 任务,这个目录就会创建。这里包含你应用程序的 war 文件。包括 license 信息,文档和您准备的 Readme 文件。
这两个文件夹不应该上传到您的源码控制系统中,因为它们在开发时需要频繁的删除和重新生成。如果您想要永久的保留修改,就不应该在这两个文件中编辑任何源码文件,因为下次编译时它们就会自动删除。
当你的应用程序需要其他工程的 Jar 文件或资源的话应该怎么做?例如需要将 JDBC 驱动加入 web 应用程序中。
对于这个问题每一个开发者都有自己的解决方案。一些人建议将 Jar 文件也保存到相应程序的源码控制系统中。但这样带来的最严重的管理问题是您在许多程序中使用同样的 Jar 文件,尤其是需要更新不同版本的 Jar 文件时。
所以,本文不建议这种方式。外部资源应该是构建程序的一部分。使用这种方式,您可以得到开发系统管理员安装的合适版本的 Jar 文件,不需要每次 Jar 文件修改时都去更新。
在 build.xml 文件例子中,我们提供如何定义构建属性的方式来查找需要拷贝的文件,而且当这些文件变化时不需要修改。构建属性是由一个特殊的开发者在程序开发前准备的,或者是开发者自己的目录中的 standard 构建属性。
有些时候,您的开发系统管理员已经将 Jar 文件安装在 Tomcat6.0 的 common/lib 或 shard/lib 目录下。这样的话您什么都不用做,直接运行 build.xml 文件就可以了。
上文已经提到,强烈建议您将应用程序中所有的源码文件保存在像 CVS 一样的源码控制系统中。如果您这样做了,那么所有的源码文件和目录结构都应该注册和保存,除了生成的文件之外。如果您注册了二进制类型文件(图像或 Jar 文件),请确定它们指向源码控制系统。
建议不要将 build/ 和 dest/ 目录下的内容保存在源码控制系统中。让 CVS 忽略目录的一个简单方式就是在源码目录的最上层创建一个名叫 .
cvsignore 的文件,包含如下内容:
build
dist
build.properties |
在这里声明 build.properties 的含义将会在 Process 一节说明。
对于源码控制的详细内容不再本手册中进行介绍,以下介绍一些在命令行使用 CVS 的常用命令:
l 进入您的源码目录下,键入 cvs update –dP 命令,更新源码和源码库同步。
l 如果需要在源码中添加文件夹,将文件夹在 CVS 中注册的命令是 cvs add [ 文件夹名 ]
l 当您创建了一个新的源码文件,进入源码文件的目录,使用 cvs add [ 文件名 ] 的方式在 CVS 中注册。
l 如果需要删除文件,进入文件所在的目录,使用 cvs remove [ 文件名 ] 的方式进行删除。
l 当您创建,修改以及删除源码文件时,修改不是立即反映在源码库的服务器中。要保存当前修改,进入源码文件的目录下,使用 cvs commit 命令提交代码。提交时需要写一个简要说明,简要说明和源码将会作为一个新版本进行保存。
CVS 和其他源码控制系统一样,有许多其他的功能(比如可以为特殊的发行版本打标签或支持多分支开发和合并)。详细信息请查看说明中提到的 CVS 链接。
我们使用 ant 进行 Java 源码的编译和部署目录结构的生成。需要编写一个称为 build.xml 的文件地给定义 ant 的执行流程。这个文件保存在您源码结构的最上层,应该同时受到源码控制系统的保护。
和 MakeFile 一样, build.xml 文件提供一些“目的( targes )”,这些 targets 一些开发中需要的功能,比如生成相关的 Javadoc 文档,清理部署文件夹,创建用来发布的 WAR 文件等。一个格式良好的 build.xml 文件应该提供描述 target 作用以及使用方式的内部文档。如果需要查看这些文档,进入包含 build.xml 文件的目录,键入以下命令:
ant -projecthelp |
示例中提供了一个基本的 build.xml 文件,您可以将它拷贝到您应用程序的工程源码目录下并做任何需要的修改。这个文档在注释中为每一个 target 提供了详细的说明。以下列出常用 target 的简单介绍:
l clean :这个 target 删除 /build 和 /dist 目录下的所有文件用于重新构建系统。这样做的好处在于避免了因为部分文件没有编译导致的运行时错误。
l compile :这个 target 用来编译已经修改了的源码文件。编译后的结果保存在 /WEB-INF/classes 子目录下,在文件夹中类的层次结构和源码文件中的完全一致。因为这个命令是最经常使用的,所以它被作为默认的 target ,当您输入 ant 时就会执行这个命令。
l all : 这个命令是 clean 和 compile 两个命令的集合,先执行 clean ,然后执行 compile 。这样当工程中有任何未知的不兼容修改发生时,可以重新编译引用程序中的所有文件。
l javadoc : 这个 target 创建当前 web 应用程序中的 Javadoc API 文档。示例 build.xml 文件中假设您需要在应用程序发布时包含 Javadoc 文档,执行这个命令后,可以在 /dist 目录下找到这些文档。因为您不是每次都要生成 Javadoc 文档,所以这个命令是 dist 命令的一部分,但不是 compile 命令的一部分。
l dist : 这个 target 为您的应用程序创建所有发布用的信息,包括所有文档, JavaDoc 文档以及 WAR 文件。因为这个 target 依赖 depoly 命令, WAR 文件将会执行编译相关的所有依赖信息。
以下附加的 target 可以让您使用 Tomcat6.0 交互的开发和测试您的 web 应用程序:
l install : 告诉正在运行的 Tomcat6.0 您需要立即执行和测试应用程序。这个动作不需要重启 Tomcat6.0 ,而且当 Tomcat 下次启动时不会记录任何信息。
l reload : 当一个应用程序安装后,您可以继续进行修改并使用 compile 命令重新编译它。 Tomcat6.0 可以立即认出 JSP 页面的修改,但不能认出 servlet 或其他 font-family: Times New Roman