在 这个分为五部分的系列的第一篇文章 中,我介绍了 Shale 并解释了它与它的前一代 Struts 的不同之处。文中介绍了 Shale 的理论基础并为您演示了如何安装和设置开发环境。还讨论了 Shale 可能存在的一些弱点 —— 也就是它是一个正在发展中的产品 —— 但我们也得出了结论,对于那些愿意随其不断改进和学习的开发人员来说,Shale 是一个很有前途的新开发框架。
在本文中,我把改进与学习这一项放到测试中,同时对 Shale 应用程序进行彻底深入的分析。本文首先重新探讨 Shale 所谓的 starter 应用程序(您将很快发现,这实际上是一个模板),以便您能确切地了解它为 Web 应用程序开发带来的好处。使用 starter 应用程序构建您自己的示例应用程序,然后使用它们浏览许多构成最基本的 Shale 应用程序的文件和目录。在本文中,我将为您说明把 JSP 和 Java™ 类放在何处并解释 Shale 是如何简化构建功能全面的、定制的 Web 应用程序的过程。
本文中的大多数讨论以本系列第一篇文章介绍的知识为基础。如果您还未曾阅读那篇文章,您应该 立即阅读。
开始使用 Shale
正如您在上一篇文章中学到的,开始构建 Shale 应用程序的最容易的方法就是以 Shale starter 应用程序作为模板,然后在此基础上进行修改。因为本文非常需要您进行实际操作,因此现在您首先要做的是启动该 starter 应用程序。学习 starter 程序中的各种组件(通过应用程序的目录结构)及其协同工作的方式对稍后谈到的创建自己的 Shale 应用程序很有帮助。
|
实际上,使用 starter 应用程序开始 Shale 应用程序开发项目总 是一个好主意。我在上一篇文章中说明了设置 Shale starter 应用程序的过程,本文假定您已完成了那些基础工作。您应该已经把 Shale starter 应用程序复制到开发环境中称为 “first-shale” 的目录中。first-shale 目录中的代码是您个人的 starter 应用程序,您将使用它们了解所有的 Shale 应用程序结构。
核心目录结构
假定您已经从 Shale starter 应用程序复制了自己的应用程序(first-shale),查看一下应用程序的目录结构。您将看到许多文件。如果不能确定每个组件、文件和目录的具体用途,应用程序能够显示出一些它们的主要用处 —— 至少在开始时。图 1 显示的是目录结构;如您所见,starter 应用程序中有许多文件:
首先从展开 Shale starter 应用程序目录结构开始。
与构建有关的文件
starter 应用程序根目录下的前两个文件是 build.xml 和 default.properties。如果您使用过 Ant 构建环境,应该对第一个文件比较熟悉。总体来说,build.xml 告知 Ant 做什么。就 Shale starter 应用程序而言,它使 Ant 了解编译哪些文件以及如何创建 WAR 分发和 servlet 引擎(本文稍后深入讨论)所用的文件。
default.properties 文件是用来指定几个 Shale 的依赖项的模板。是的,这就意味着在模板应用程序(Shale starter 应用程序)中有一个模板文件(default.properties)。由于本系列(参见 参考资料)第一篇文章已介绍了 default.properties,故这里不再讨论相关细节。大体上,把该文件复制为名为 build.properties 的新文件,对特定于环境的部分进行更改,然后使用 Ant 构建项目。在 Ant 运行时,它使用 build.properties 中指定的位置来创建 Shale 分发。
依赖目录
接下来看见上面有两个空目录: ext/ and lib/。特意将其留空,不要以为您丢失了什么。构建 Shale Web 应用程序、设置 build.properties 文件时,您必须指出 Shale 框架和 servlet 引擎应该到哪里查找依赖项。实际上,可以指定两种类型 的依赖项:
build.properties 文件提供一个指定运行时依赖项(使用 lib.dir 属性)和不应该存在于运行时 WAR 部署配置(使用 ext.dir 属性)中的编译时依赖项的途径。如果愿意,您可以仅把依赖项放置在如下目录中:
这两个空目录是专门为此而提供的。
文档
LICENSE.TXT、NOTICE.txt 和 README.txt 是简单的文档文件。这些文档详述了能够使用 Shale 的条件和能够对框架做哪些修改。它们也对设置和构建 Shale 应用程序提供简单的指导。这些文件值得阅读一遍,但是读过一遍以后,您可以忽略它们。
源代码
最后一个名为 src/ 的目录应该比较容易理解:它包含 Shale starter 应用程序的源代码。该目录包含的文件并不多,但有许多子目录。因此,它的结构看起来比实际复杂。图 2 显示了完整的、展开的源代码目录结构:
下面仔细分析一下这些子目录:
org.apache.shale.blank.WelcomeBean
是一个演示如何将 Shale 与 Beans 一起使用的简单 JavaBean。更为重要的是,它指示能把 Java 文件放置在 starter 应用程序中的何处。构建 starter 应用程序时,ANT 将自动编译 java/ 目录下的所有 Java 代码。因此,如果您添加自己的代码,可以把代码放在 java/ 目录(目录结构等等)下,Ant 编译这些代码并把它们包含在应用程序的构建中。很明显,大多数令人感兴趣的 Shale starter 的组件位于 src/ 目录下。开发愈加复杂的 Shale 应用程序时,您的 src/ 目录将装满您自己的 Java 类和 JSP。因此要习惯于在 Shale starter 应用程序的 src/ 目录结构下工作;您将发现这在应用程序开发中会非常有用。
|
创建应用程序
一旦很清楚 starter 应用程序的最初目录结构,您将深入分析构建 Shale 应用程序时它是什么样子。 在上一节,您看到了 Shale 应用程序的源代码位于何处。在本节中,将学习如何把源代码构建到 Web 应用程序中以及把所有已编译的 Java 文件、JSP 页面和相关的依赖项放置在何处。
在创建过程中,您将很好地理解如何部署 Shale 应用程序以及可以在何处修改标准部署选项。您也会知晓在何处添加用于附加插件或想要和 Shale 代码一起使用的依赖项的库。
构建 starter 应用程序
回顾一下上一篇文章中介绍的 starter 应用程序的构建方式,下面让我们简单回顾一下:
ant
,从而使用 ant 构建应用程序。 添加到源代码树
前面已经提到过,您可以轻松地把自己的 JSP 添加到 Shale starter 应用程序的 src/web/ 目录中。该目录中的所有 JSP 都将自动添加到构建进程中。Java 源文件也是如此。src/ 目录中有一个名称为 java/ 的子目录。只需要把 Java 源文件放在该目录下,它们将作为构建进程的一部分被编译。
如果您还不太相信使用 Shale starter 应用程序的价值,构建进程应该能证明它非常有用。通过编辑单个文件 —— build.properties —— 您可以构建自己的应用程序,而且毫不费力。即使在使用 Ant(用于 Shale starter 应用程序的构建系统)时,也必须设置所有的目录、依赖项和构建 Web 应用程序需要的规则。但使用 Shale starter 应用程序,可以把时间精力用在编写 JSP 和 Java 类上,将文件拖放到正确的位置,键入 ant
即可。
当提到放置 Java 类文件时,通常来说,应使用与 Java 类的包结构相匹配的目录结构。例如,如果类名称为 Song
,该类在包 com.nathanson.music
中,则应把 Song.java 文件放在 src/java/com/nathanson/music 目录结构中。这不会改变 Java 编译文件的方式 —— javac
只查看 Song.java 顶部的 package
指令 —— 但这是一种良好的代码组织结构。
|
target/ 目录
只要运行 ant
并构建应用程序,就能看到一个名为 target/ 的新目录。该目录包含从 src/ 目录的源代码构建而来的所有文件。实际上,target/ 目录包含 “分解的 WAR”。WAR 文件只是 JAR 文件和一些额外的配置信息,以一种所有 Servlet 容器都能在里面部署应用程序的方式构建。如果取出一个 WAR 并展开它 —— 即解压缩,最终将得到 target/ 目录下的一个目录结构。(我马上解释 WAR 文件的实际创建方式。)
了解 Shale 应用程序源文件位置的最好方法是查看 starter 应用程序的 src/ 目录。同样地,理解一个已部署的 Shale 应用程序的形式的最佳方法就是查看 target/ 目录。首先,我解释在构建过程中 Shale 将各种文件放置在何处,然后为您演示如何设置它以部署应用程序。
target/ 目录内部
启动 Ant 后,打开已创建的新 target/ 目录。该目录下的内容如图 3 所示。
该图中很多内容看起来与在前面 图 2 中展示的 src/ 目录结构相似。像在 src/ 目录中一样,您可以看出标准 Web 应用程序结构,包括 Java 类和 JSP 页面。但文件顺序有些变化,而且增加了几项内容。
主应用程序目录
target/ 目录的所有内容几乎都位于名为 first-shale/ 的子目录中。如果您在 build.properties 文件中指定了一个不同的项目路径,在您的系统上该目录名称可能有所不同。不管它的名称是什么,清单 1 显示用于构建应用程序的文件:
|
可任选名称作为项目路径。Shale 构建脚本(使用 Ant)直接使用您为它在 target/ 下创建的目录所指定的名称。
manifest 文件
本文其余部分主要关注 target/ 目录中的内容 —— 但深入学习之前,您应该了解直接在 target/ 下创建的目录的内容。META-INF/ 目录只包含一个名为 MANIFEST.MF 的文件,如清单 2 所示:
|
将该文件的内容与 清单 1 和输入 build.properties 文件中的信息相比较,应立即能看出某种关联。MANIFEST.MF 从 build.properties 获得包名、项目供应商和项目供应商 ID,并把这些内容插入到该文件中。
使用 Shale 构建进程来构建部署到 servlet 引擎中的 WAR 文件时,该 manifest 文件将作为 WAR 的一部分包含进来,用它来确定内容。如果您使用任何 GUI 工具管理 servlet 引擎,这些工具能读取 MANIFEST.MF 文件并让您或其他系统管理员了解 WAR 中包含什么。
通常,不应该手动更改 MANIFEST.MF;实际上,如果需要修改它的值,则应该更新 build.properties 并且重新构建应用程序。如果您想独立地更改 MANIFEST.MF —— 而不更改 build.properties —— 然后重新构建项目,所有更改都将会丢失。通过使用 build.properties 控制 target/ 目录中的所有内容以及控制 src/ 目录中的所有内容,能够确保您的可部署的应用程序总是与开发完成的源代码和 build.properties 中为该代码编写的信息一致。
|
典型 Web 应用程序
如果您编写过任何类型的 Web 应用程序 —— 不管它是使用像 Struts 这样的框架还是单独编写 JSP 和 Servlet 代码 —— 应该已经熟悉了 Web 应用程序的基本结构。您在 target/first-shale/ 目录下能够看到同样的结构,看到像 META-INF/ 和 WEB-INF/ 这样的目录不应感到很惊奇。
包含在 src/web/ 目录下的所有 JSP 文件现在都放入 Web 应用程序的根目录中。您看 index.jsp、 welcome.jsp 和 messages.jspf — 在 src/web 目录下的三个 JSP 和 与 JSP 相关的文件 — 都直接位于 target/first-shale/ 目录下。
根目录(first-shale/)是所有 JSP 文件的所在;但若需要向应用程序添加更多的 JSP,不要 只是把它们放到该目录下。应该把附加的 JSP 放置在 src/web/ 目录下,然后重新构建应用程序。如前所述,Shale 编程(对于任何 Web 编程都一样)能实现的一个重要功能就是使源代码树和部署树保持同步。只要在 src/ 目录结构中进行所有更改,就不会有任何问题。
定位 Java 类
Java 类位于 target/first-shale/WEB-INF/classes/ 目录结构中。这是任何 Web 应用程序中 Java 类的标准位置,因此不应对它感到惊奇。您能在该结构中找到所有已编译的 Java .class 文件,这些文件嵌套在与包结构相匹配的目录结构中。因此在 org.apache.shale.blank
包中的 WelcomeBean
类文件,是位于 classes/org/apache/shale/blank 目录结构中的 WelcomeBean.class。
与源代码与二进制代码之间的分离相一致,在 classes/ 目录结构中没有 .java 文件 —— 这里不应该有!实际上,只有已编译的 Java 文件存在;像 JSP 一样,应该把新的 Java 源文件放在 src/ 目录中的 java/ 子目录下,并且让 Shale 构建脚本编译 Java 代码。
构建脚本还会把 src/java/ 目录结构中的属性文件复制过来;例如,target/ 目录中有 Bundle.properties(参考前面的 图 3),该文件位于 src/java/ 目录下。这允许您把 Java 类可能需要的文件与 Java 源文件放在一起,从而可在应用程序构建结构使用它们。
大量的依赖项
target/first-shale/WEB-INF/ 下的 lib/ 目录包含应用程序运行需要的所有库。前面已经提到,Shale 有大量的依赖项:
Shale starter 应用程序的一个重要特性是在构建期间它为您照管这些依赖项。现在不详细介绍这些依赖项的功能。您将在特定的编程任务或上下文中学习它们。但要注意,其余部分的讨论假定您使用过 starter 应用程序并且已经拥有全部依赖项。如果您尝试从头开始构建 Shale 应用程序 —— 不使用 starter 应用程序作为模板 —— 则需要您自己添加所有的依赖项。这正是总是使用 Shale starter 应用程序开始开发的另一原因。
|
在 starter 应用程序中,您在 WEB-INF/lib/ 目录下找到依赖项,它们均为 JAR 文件。同样,这也是 Web 应用程序中 JAR 文件的标准位置,因此不应该对它感到惊奇。您还能找到实际 Shale 库 —— shale-core.jar —— 以及几个使 Shale 能与其他框架(例如,Spring (shale-spring.jar)、Clay (shale-core.jar)、Tiles (shale-tiles.jar)和 Java 5.0 Tiger (shale-tiger.jar))协同工作的 Shale 插件。换言之,您已经拥有了使用 Shale 开发 Web 应用程序所需的所有库。这很容易,不是吗?
部署应用程序
我们已经编写好了源代码并构建了应用程序。完成这两步之后,所得到的结果是一个包含将应用程序部署到 servlet 引擎中所需全部文件的目录结构(first-shale/ 主目录下的 target/ 目录)。但是,保持所有这些文件并复制整个目录并不方便,也不安全。幸运的是,Shale 提供了一种部署应用程序的简便方式。
构建 WAR 文件
上篇文章介绍了 WAR 文件的构建方法,简要回顾如下:
ant dist
。 完成这些步骤,即可得到一个新目录,名为 dist/。该目录中的内容如图 4 所示:
这里最值得注意的文件是 first-shale-0.1.war,它是根据 build.properties(如前面 清单 1 所示)中提供的值命名的。dist/ 目录还包含与 Shale 和源代码相关的许可和自述信息。在您需要把整个应用程序移动到其他计算机上( 例如其他开发服务器或工作站)时,这使您可轻松地将整个 dist/ 目录打包为一个 ZIP 文件。但在许多情况下,您只会在一台计算机上开发应用程序,因此您最感兴趣的是 WAR 文件。
部署 WAR 文件
有了 WAR 文件后,实际部署应用程序是件很容易的事。获取文件并把它们放在 Servlet 引擎为 Web 应用程序提供的目录中即可完成部署。通常该目录的名称形式为 webapps/。然后 Servlet 引擎展开 WAR 文件(得到您在 target/ 中看到的目录结构)并部署应用程序。这时,就得到了可供使用的应用程序。
|
结束语
在本文中,我们剖析了 Shale 应用程序。您以一个 Shale 应用程序为背景学习了各目录的用途 —— 以及几乎每个目录下的每个文件 —— 从构建到部署应用程序。现在,您应清楚地了解了 Shale Web 应用程序源代码目录和最终展开的 WAR 文件的内容。
在阅读我的下一篇文章之前最好自行练习实践。如果您有一个想要将其转换为 Shale 的 Web 应用程序,那么完成它。从将其所有的 JSP 和 Java 文件移动到 Shale 目录结构开始。只需记住将所有的 JSP 放在 src/web/ 目录下,将所有的 Java 类嵌套入 src/java/ 目录中。随后即可构建并部署应用程序了。
的确,单纯的目录剖析与 Shale 组件的实际使用并不一样,但您在使用 Shale 应用程序基础设施,这是迈往正确方向的重要一步。(非常重要,所以我用一整篇文章解释 Shale 在何处放置源代码和部署形式的文件。)在下一篇文章中,我将进一步为您演示如何编写与 Shale 交互的代码。我将从 JSP 开始,然后介绍一些可以用于 JSP 页面的 Shale 相关标记。迄今为止,我介绍的还只是一些浅显的 starter 应用程序方面的知识。做出更改并完成们测试 —— 一定要使源代码树与部署树保持同步!