源代码组织

目录

目录结构

以下描述使用变量名 $CATALINA_BASE 来指代大部分相对路径解析所依据的基础目录。如果您尚未通过设置 CATALINA_BASE 目录来为 Tomcat 配置多个实例,那么 $CATALINA_BASE 将被设置为 $CATALINA_HOME 的值,即您安装 Tomcat 的目录。

本手册的一个关键建议是将包含源代码的目录层次结构(本节所述)与包含可部署应用程序的目录层次结构(上一节所述)分开。保持这种分离具有以下优点:

  • 如果应用程序的“可执行”版本未混合在一起,则源目录的内容可以更容易地进行管理、移动和备份。

  • 在仅包含源文件的目录上,源代码控制更易于管理。

  • 当部署层次结构分离时,组成应用程序可安装分发版的文件更容易选择。

正如我们将看到的,ant 开发工具使得创建和处理此类目录层次结构几乎是无痛的。

用于存放应用程序源代码的实际目录和文件层次结构可以随心所欲。然而,以下组织结构已被证明非常普遍适用,并且是下文讨论的示例 build.xml 配置文件所期望的。所有这些组件都存在于您的应用程序的顶级项目源目录下:

  • docs/ - 您的应用程序的文档,采用您的开发团队正在使用的任何格式。

  • src/ - 生成您的应用程序特有的 servlet、bean 和其他 Java 类的 Java 源文件。如果您的源代码是按包组织的(强烈推荐),则包层次结构应在此目录下反映为目录结构。

  • web/ - 您的网站的静态内容(HTML 页面、JSP 页面、JavaScript 文件、CSS 样式表文件和图像),这些内容将对应用程序客户端可见。此目录将是您的 Web 应用程序的文档根目录,此处找到的任何子目录结构都将反映在访问这些文件所需的请求 URI 中。

  • web/WEB-INF/ - 您的应用程序所需的特殊配置文件,包括 Web 应用程序部署描述符(web.xml,在Servlet 规范中定义)、您已创建的自定义标签库的标签库描述符,以及您希望包含在 Web 应用程序中的其他资源文件。尽管此目录看起来是您的文档根目录的子目录,但 Servlet 规范禁止将此目录(或其包含的任何文件)的内容直接提供给客户端请求。因此,这是存储敏感配置信息(例如数据库连接用户名和密码)的好地方,但这些信息对于您的应用程序成功运行是必需的。

在开发过程中,将临时创建两个额外的目录:

  • build/ - 当您执行默认构建(ant)时,此目录将包含此应用程序的 Web 应用程序归档中文件的精确镜像。Tomcat 允许您部署一个未打包的目录形式的应用程序,可以通过将其复制到 $CATALINA_BASE/webapps 目录,或通过“管理器”Web 应用程序安装它。后一种方法在开发过程中非常有用,并将在下文说明。

  • dist/ - 当您执行 ant dist 目标时,将创建此目录。它将创建您的 Web 应用程序二进制分发版的精确镜像,包括您已准备好的任何许可信息、文档和 README 文件。

请注意,这两个目录不应归档到您的源代码控制系统中,因为它们在开发过程中根据需要会被删除并(从头开始)重新创建。因此,如果您想保留更改的永久记录,则不应编辑这些目录中的任何源文件,因为下次执行构建时,更改将丢失。

外部依赖

如果您的应用程序需要来自外部项目或包的 JAR 文件(或其他资源),您该怎么办?一个常见的例子是您需要在 Web 应用程序中包含一个 JDBC 驱动程序才能运行。

不同的开发人员对此问题采用不同的方法。有些人会鼓励将您依赖的 JAR 文件副本检入到每个需要这些 JAR 文件的应用程序的源代码控制存档中。然而,当您在许多应用程序中使用相同的 JAR 时,这可能会导致重大的管理问题——尤其是在需要升级到该 JAR 文件的不同版本时。

因此,本手册建议您不要在应用程序的源代码控制存档中存储您依赖的软件包的副本。相反,外部依赖项应作为构建应用程序过程的一部分进行集成。这样,您始终可以从开发系统管理员安装它们的位置获取适当版本的 JAR 文件,而无需担心每次依赖 JAR 文件的版本更改时都更新您的应用程序。

在示例 Ant build.xml 文件中,我们将演示如何定义构建属性,让您配置要复制文件的位置,而无需在这些文件更改时修改 build.xml。特定开发人员使用的构建属性可以按应用程序进行自定义,也可以默认设置为存储在开发人员主目录中的“标准”构建属性。

在许多情况下,您的开发系统管理员已将所需的 JAR 文件安装到 Tomcat 的 lib 目录中。如果已完成此操作,则您无需采取任何措施——示例 build.xml 文件会自动构建一个包含这些文件的编译类路径。

源代码控制

如前所述,强烈建议您将组成应用程序的所有源文件置于源代码控制系统的管理之下。如果您选择这样做,源层次结构中的每个目录和文件都应注册并保存——但生成的任何文件不应注册。如果您注册二进制格式文件(如图像或 JAR 库),请务必向您的源代码控制系统指明这一点。

我们建议(在上一节中)您不应将开发过程中创建的 build/dist/ 目录的内容存储在源代码控制系统中。源代码控制系统通常提供忽略这些目录的机制(Git 使用 .gitignore 文件,Subversion 使用 svn:ignore 属性,CVS 使用 .cvsignore 文件等)。您应该配置您的源代码控制系统来忽略:

  • build
  • dist
  • build.properties

在此提及 build.properties 的原因将在流程一节中解释。

有关您的源代码控制环境的详细说明超出了本手册的范围。

BUILD.XML 配置文件

我们将使用 ant 工具来管理 Java 源代码文件的编译以及部署层次结构的创建。Ant 在构建文件(通常称为 build.xml)的控制下运行,该文件定义了所需的处理步骤。此文件存储在源代码层次结构的顶级目录中,应检入您的源代码控制系统。

与 Makefile 类似,build.xml 文件提供了几个“目标”,支持可选的开发活动(例如创建相关的 Javadoc 文档、擦除部署主目录以便您可以从头开始构建项目,或者创建 Web 应用程序归档文件以便您可以分发应用程序)。一个构建良好的 build.xml 文件将包含内部文档,描述为开发人员设计的目标与内部使用的目标。要让 Ant 显示项目文档,请切换到包含 build.xml 文件的目录并输入:

ant -projecthelp

为了让您有一个好的开始,我们提供了一个基本的 build.xml 文件,您可以自定义并将其安装在您的应用程序的项目源目录中。此文件包含描述可执行的各种目标的注释。简而言之,通常提供以下目标:

  • clean - 此目标删除任何现有的 builddist 目录,以便可以从头重建它们。这使您能够保证没有进行可能由于未重新编译所有受影响类而在运行时导致问题的源代码修改。

  • compile - 此目标用于编译自上次编译以来已更改的任何源代码。生成的类文件将在您的 build 目录的 WEB-INF/classes 子目录中创建,这正是 Web 应用程序结构所要求的位置。由于此命令在开发过程中经常执行,因此通常将其设置为“默认”目标,以便简单的 ant 命令即可执行它。

  • all - 此目标是运行 clean 目标后紧跟 compile 目标的快捷方式。因此,它保证您将重新编译整个应用程序,以确保您没有在不知不觉中引入任何不兼容的更改。

  • javadoc - 此目标为此 Web 应用程序中的 Java 类创建 Javadoc API 文档。示例 build.xml 文件假设您希望将 API 文档与您的应用程序分发版一起包含,因此它在 dist 目录的子目录中生成文档。因为您通常不需要在每次编译时都生成 Javadoc,所以此目标通常是 dist 目标的依赖项,但不是 compile 目标的依赖项。

  • dist - 此目标为您的应用程序创建一个分发目录,包括任何所需的文档、Java 类的 Javadoc,以及一个将交付给希望安装您的应用程序的系统管理员的 Web 应用程序归档(WAR)文件。由于此目标也依赖于 deploy 目标,因此 Web 应用程序归档也将包含在部署时包含的任何外部依赖项。

为了在 Tomcat 中进行 Web 应用程序的交互式开发和测试,定义了以下附加目标:

  • install - 告知当前运行的 Tomcat 立即提供您正在开发的应用程序以供执行和测试。此操作不需要重新启动 Tomcat,但在下次重新启动 Tomcat 后也不会被记住。

  • reload - 应用程序安装后,您可以继续使用 compile 目标进行更改和重新编译。Tomcat 将自动识别对 JSP 页面的更改,但不会识别对 servlet 或 JavaBean 类的更改——此命令将告诉 Tomcat 重新启动当前安装的应用程序,以便识别此类更改。

  • remove - 当您完成开发和测试活动后,您可以选择性地告诉 Tomcat 将此应用程序从服务中移除。

使用开发和测试目标需要额外的、一次性的设置,这将在下一页进行描述。