在 SpringSource dm Server 中部署 GWT 应用程序 - 第 1 部分

工程 | Ben Corrie | 2008 年 11 月 7 日 | ...

引言

本系列共 3 篇博客,将逐步介绍在 SpringSource dm Server™ 中构建和部署 GWT 应用程序的方法。博客的重点如下
  1. 使用 SpringSource Tool Suite 从头开始构建并将 GWT StockWatcher 示例应用程序作为 WAR 文件部署到 dm Server 中。
  2. 采用“共享库”方法进行部署:如何从 WAR 中移除 GWT 依赖项并将其作为 OSGi bundle 部署到 dm Server 中。
  3. 采用“共享服务”方法进行部署:我们将单个 WAR 文件转换为 OSGi 服务,这些服务可以由其他应用程序共享并支持热插拔。
值得注意的是,在前两篇博客中我没有使用 Spring Framework。Spring 和 GWT 的集成本身就是一个课题,我想尽量让每篇博客都保持重点突出。在第三篇博客中,我将展示如何使用 Spring 发布和消费 OSGi 服务以及如何将其与 GWT 集成。

背景

本博客将采用实践逐步方法构建此处描述的 GWT StockWatcher 示例。Google 教程逐步指导您如何使用 RPC 从头开始构建一个 GWT 示例。在学习过程中,我将参考教程中的页面,并讨论各种方法的优缺点。

本博客假设您已安装 SpringSource Tool Suite 1.1.1(我使用的是 Eclipse 3.4 版本)、  dm Server 1.0.0GWT 1.5。它还假设您对 Java 编程有很好的理解,并对 Javascript 和 Ajax 有基本了解。

为了演示中使用的路径,我在以下位置创建了一个新的 Eclipse 工作区/Users/bcorrie/gwt/workspace。我包含了可以下载的压缩项目,其中包含一个GWT_ROOT_INSTALL我已定义的变量。要使用我的项目,导入后请导航至“Preferences”->“Java”->“Build Path”->“Classpath Variables”,然后定义您自己的GWT_ROOT_INSTALL.

步骤 1:创建一个新的 GWT 项目

目前创建 GWT Eclipse 项目的最简单方法是使用 GWT 分发版附带的命令行工具projectCreatorapplicationCreator,使用-eclipse参数,如此处所述。这些命令行工具会创建一个简单的 Java 项目、骨架项目文件、一个用于在托管模式下运行项目的 Run Configuration,以及在 Eclipse 外部运行或编译项目的脚本。

这些工具的一个限制是它们对源代码的位置有规定。您的源代码必须位于项目子目录中,该目录名为/src,您的客户端代码必须位于以client结尾的包中,您的服务器代码必须位于以server结尾的包中。它们projectCreatorapplicationCreator无法配置为执行其他操作,因为这通常是GWTShellGWTCompiler和 期望您的代码所在的位置。稍后,我们将研究一些重新组织源代码和调整运行配置以使其更灵活的方法。

在命令行创建项目后,将其导入 STS。

使用“Import”->“General”->“Existing Projects into Workspace”。

步骤 2:按照 Google 教程开发 Java 源代码

请确保您继续完成“基础知识”部分,并接着处理“使用远程过程调用”部分。关于远程过程调用的部分将确保您的股票价格更新代码在 Web 服务器上运行,该代码将每隔 5 秒动态更新网页。这提供了一个简单但功能强大的演示,展示了 Ajax 的能力以及 GWT 如何在 Java 代码中抽象该行为。您应该最终得到一个看起来像这样的项目

如果您不想亲自开发示例代码,您可以在此处下载我初始项目的压缩副本。要使用我的项目运行,您需要执行以下步骤

- 解压并导入项目(“Import”->“Existing Projects Into Workspace”) - 定义一个GWT_ROOT_INSTALL变量,如上面背景部分所述 - 修改已包含的StockWatcher GWTShell.launch运行配置,或创建具有以下值的新配置

- 右键单击 StockWatcher 项目 ->“Run As”->“Run Configurations” - 对于“Main class”,输入com.google.gwt.dev.GWTShell- 在“Program arguments”中,输入-out www com.google.gwt.sample.stockwatcher.StockWatcher/StockWatcher.html- 仅在 Mac OS X 上,在“VM arguments”中,输入-XstartOnFirstThread- 在“Classpath”->“User Entries”中

- 添加gwt-dev-<os>.jar(例如:gwt-dev-mac.jar) - 添加 StockWatcher 项目/src文件夹,使用“Advanced”->“Add Folders”

请注意,将/src文件夹添加到 classpath 是 GWTShell 的要求,因为它需要将元数据(例如 .xml 文件)添加到 Java classpath 中。

步骤 3:在托管模式下运行 - 检查是否正常工作!

托管模式允许您在部署 GWT 应用程序之前,在其“预编译”的 Java 状态下运行和调试它。请在此处阅读有关托管模式的信息。重要的是要记住,StockWatcher 应用程序的客户端类最终将被编译成 javascript 和 html,部署在客户端,而服务器类将作为正常的 Java 代码在服务器上运行。令人困惑的是,一些客户端代码既在服务器上用作支持类,也在客户端用作编译后的 javascript。当我们稍后开始拆分项目时,这一点会变得更加清晰。

选择 StockWatcher 项目后,单击“Run”按钮,或选择您在步骤 2 中创建的运行配置。

另请注意,当您在托管模式下运行时,GWTShell会创建一个/www输出文件夹到您的项目中,以及一个/tomcat文件夹来配置嵌入式 Tomcat。在测试后刷新 StockWatcher 项目,您将看到这些文件夹。

步骤 4:创建一个新的动态 Web 项目

要创建一个 WAR 文件,我们需要一个动态 Web 项目……但我们已经有了一个 Java 项目!那么管理这个需求的最佳方法是什么?Google 建议将编译后的代码生成到 Eclipse Java 项目中,然后将 GWT 编译器输出和生成的 .class 文件剪切粘贴到单独的 WAR 项目中。我更倾向于设置 GWT 编译器直接将部署代码构建到 WAR 项目中,并且将源代码拆分到两个项目中,这样客户端代码位于 Java 项目中,服务器代码位于 WAR 项目中。

那么为什么不把所有东西都复制到 WAR 项目并在那里运行呢?我认为保持两个独立的项目有几个原因

首先,您不希望您的托管模式生成其/www/tomcat文件夹到您的 WAR 项目中。

其次,将托管模式项目生成的 javascript 和 html 代码放入 WAR 项目中,这样做的好处是能保持两个项目更清晰,并分离关注点。它消除了生成代码的重复,这可能导致版本混淆,特别是考虑到生成的代码是混淆的。

第三,如步骤 1 中所讨论的,GWTShellGWTCompiler强制您的源代码位于名为/src的子目录中。这限制了您的 WAR 项目与 Maven 和 Ant 等工具集成的便利性。

最后,它还允许分离 Java 代码,这样您就不会将冗余的客户端代码复制到 WAR 文件中。

虽然这可能看起来是不必要的额外工作,但随着我们继续探索不同的方法,您将明白为什么尽早拆分代码有助于稍后将其部署为共享服务。

所以让我们创建一个新的动态 Web 项目,同时创建一个 dm Server 的服务器实例。

如果您的工作区中还没有 dm Server 实例,您需要点击“Target Runtime”文本字段旁边的“New”按钮,然后选择“Create a new local server”。请注意,我还选择了src/main/javasrc/main/webapp作为“Java Source Directory”和“Content Directory”。您可以使用默认值,但推荐这些路径,因为它们与 Maven 等构建工具集成良好。

接下来,我们将把 Java 代码拆分到两个项目中

请注意,如果您仅将 GWT 代码导出为普通的 WAR 文件,则此代码划分并非必需。实现这一点的最简单方法是将您的 Java 项目创建为 WAR 项目的 Java EE 依赖项,Eclipse 会将您的 Java 项目转换为 JAR 文件并添加到 WAR 的 WEB-INF/lib 中。然而,这种方法的问题在于,您会将冗余的客户端代码打包到 WAR 中,并且使得稍后将应用程序拆分为服务变得更加困难。

因此,我们的项目中有 3 种类型的 Java 代码:只编译为 javascript 和 html 的代码、纯粹的服务器端代码以及同时支持这两种目的的代码。将后两种类型的代码移到我们的 WAR 项目中是有意义的。将我们的“公共”类(客户端和服务器都使用的类)放入一个单独的包中也是有意义的(同样,这样做的必要性在博客 3 中会更清晰),我们将称之为com...client.api。最后,GWT 要求我们的 Async 接口与 RemoteService 接口位于同一个包中,因此将此重构到com...client.api包中。完成后,它应该看起来像这样

拆分代码所需的最后一件事是将 StockWatcherWar 项目添加到 StockWatcher 项目的构建路径中,以便它可以访问com...client.api包中的类(Properties -> Java Build Path -> Projects -> Add...)。

如果您愿意,可以通过此处下载我的两个完成的项目以及各种运行配置的 zip 文件来跳过所有这些繁重的工作(有关导入和设置的说明,请参阅步骤 2 和背景)。如果您有一个干净的工作区,您需要创建一个 dm Server 运行时实例(New -> Server -> SpringSource ...),并且您可能需要在 WAR 项目的“Properties”->“Targeted Runtimes”中选择服务器运行时,因为它可能与我的不匹配。

步骤 5:配置 GWTCompiler 将客户端代码生成到 WAR 项目中

我们需要设置 GWT 编译器将代码从 StockWatcher 项目生成到 StockWatcherWar 项目中。这个过程与步骤 2 中设置 GWTShell 的过程几乎相同。您可以修改已包含的StockWatcher GWTCompiler.launch脚本,该脚本包含在步骤 4 的项目 zip 文件中,或者创建具有以下值的新脚本

- 右键单击 StockWatcher 项目 ->“Run As”->“Run Configurations”,然后创建一个新的配置 - 对于“Main class”,输入com.google.gwt.dev.GWTCompiler- 在“Program arguments”中,输入-out <path to your workspace>/StockWatcherWar/src/main/webapp com.google.gwt.sample.stockwatcher.StockWatcher- 仅在 Mac OS X 上,在“VM arguments”中,输入-XstartOnFirstThread- 在“Classpath”->“User Entries”中

- 添加gwt-dev-<os>.jar(例如:gwt-dev-mac.jar) - 添加 StockWatcher 项目/src文件夹,以及 StockWatcherWar 的/src/main/java文件夹,使用“Advanced”->“Add Folders”

请注意,将源文件夹添加到 classpath 是 Google 编译器的要求。

现在,运行您刚创建的编译器配置,然后刷新 StockWatcherWar 项目以查看生成的文件。您应该会看到类似这样的内容

步骤 6:配置 WAR 项目

您会注意到 Google 编译器将输出生成到两个文件夹中,反映了 GWT 项目的名称。编译器假定目标文件夹与源文件夹相同,且无法更改此配置,因此您必须将生成的文件拖到src/main/webapp文件夹中,然后删除这两个 Google 目录。这实际上是 Google 自己在此处推荐的做法。

接下来,我们需要在项目中添加所需的依赖项。

- 添加 Web 模块依赖项gwt-servlet.jar(“Properties”->“Java EE Module Dependencies”->“Add External Jar”)。请注意,此模块依赖于javax.servletAPI。 - 修改web.xml文件,按照 Google 的说明进行。同样值得添加StockWatcher.html到一个<welcome-file-list>中,以便部署后自动打开(尽管在 Eclipse 中部署时并非总是有效,因为浏览器窗口通常在服务器完全初始化之前打开)。

如果您遇到问题,可以查看步骤 4 中我提供的压缩项目。

步骤 7:在 STS 中部署到 dm Server

现在我们已经创建了闪亮的新 WAR 项目,让我们在 STS 中将其部署到 dm Server。只需右键单击 StockWatcherWar 项目,然后选择“Run As”->“Run On Server”。如果欢迎页面没有自动出现,请刷新页面或手动在 URL 中添加/StockWatcherWar

成功运行 WAR 项目后,您可以将托管模式配置为使用 dm Server 作为其服务器,而不是使用其嵌入式 Tomcat。为此,您只需修改GWTShell的运行配置,并将程序参数更改为-noserver -out www http://localhost:8080/StockWatcherWar/。这允许您快速测试客户端更改。服务器端更改会自动重新部署到正在运行的服务器。真棒!

需要指出的是,如果您想在我推荐的设置下在嵌入式 Tomcat 托管模式中运行,您需要暂时取消选择 WAR 项目属性中的 dm Server 作为目标运行时。这是因为将 StockWatcherWar 添加到 StockWatcher 的构建路径也会引入 dm Server 运行时包(例如javax.servlet),这会搞乱GWTShell.

的构建路径。假设这一切顺利,现在我们将 WAR 打包并在工具外部进行部署。

步骤 8:在 STS 外部导出和部署

首先,我们需要将项目导出为 WAR 文件。通过右键单击 StockWatcherWar ->“Export”->“Web”->“WAR file”来完成。如果您想知道“Overwrite existing file”复选框在哪里,那是因为 Eclipse 似乎有一个 bug,它会隐藏该复选框,直到您调整 WAR 导出对话框的大小。您可以在此处下载我导出的 WAR(注意它是压缩文件)。

导出 WAR 后,我们需要在 STS 外部启动 dm Server。

首先,确保 STS dm Server 已停止,否则它们将发生端口冲突。然后,在命令行上运行 dm Server 启动脚本。在我的情况下,这是bin/startup.sh。您可以添加-clean选项以确保您以干净的设置启动。您应该看到消息

[2008-10-27 14:14:44.468] server-dm-10             <SPPM0002I> Server open for business with profile 'web'.

成功启动后,在 Web 浏览器中打开管理控制台,使用以下 URL

http://localhost:8080/admin/web/applications/list.htm

默认用户名是admin,密码是springsource。有关运行和配置 dm Server 的更详细信息,请参阅用户指南

您现在应该看到以下内容

在“Application Location”文本字段中浏览您导出的 WAR 文件,然后单击 upload。这将上传并部署 WAR 文件,该文件随后应出现在“Deployed Applications”中

在终端输出中,您应该看到以下消息

[2008-10-27 14:07:44.380] server-tomcat-thread-5   <SPSC1000I> Creating web application '/StockWatcherWar'. [2008-10-27 14:07:44.396] async-delivery-thread-1  <SPSC1001I> Starting web application '/StockWatcherWar'. [2008-10-27 14:07:44.684] server-tomcat-thread-5   <SPDE0010I> Deployment of 'StockWatcherWar.war' version '0' completed.

最后,只需点击上面显示的/StockWatcherWar链接,您就可以开始使用您的 GWT 应用程序了!

期待第 2 部分

在下一篇博客中,我们将探讨如何利用 dm Server 的 OSGi 功能,将 GWT 依赖项从 WAR 中提取出来,并将其转换为一个 bundle,供所有在服务器中运行的 GWT 应用程序共享。我们还将稍微深入了解其内部,看看我们的 OSGi bundle 如何交互。

订阅 Spring 新闻稿

订阅 Spring 新闻稿,保持联系

订阅

抢先一步

VMware 提供培训和认证,助您快速提升。

了解更多

获取支持

Tanzu Spring 通过一个简单的订阅提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件。

了解更多

即将举行的活动

查看 Spring 社区所有即将举行的活动。

查看全部