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

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

介绍

这将是 3 篇系列博客,描述在 SpringSource dm Server™ 中构建和部署 GWT 应用程序的分步方法。博客的重点如下:
  1. 使用 SpringSource Tool Suite 从头开始构建并以 WAR 文件形式将 GWT StockWatcher 示例应用程序部署到 dm Server 中。
  2. 使用 “共享库” 方法部署:如何从 WAR 中移除 GWT 依赖项并将其作为 OSGi 捆绑包部署到 dm Server 中。
  3. 使用 “共享服务” 方法部署:我们将单个 WAR 文件转换为 OSGi 服务,这些服务可以被其他应用程序共享并热插拔。
值得注意的是,我在前两篇博客中都没有使用 Spring 框架。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 有基本的了解。

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

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

目前创建 GWT Eclipse 项目最简单的方法是使用 GWT 发行版提供的命令行工具projectCreator还是applicationCreator-eclipse参数,如此处所述。这些命令行工具创建一个简单的 Java 项目、骨架项目文件、一个用于在托管模式下运行项目的运行配置以及用于在 Eclipse 之外运行或编译项目的脚本。

这些工具的一个限制是它们规定了源代码的存放位置。您的源代码必须位于项目子目录/src中,您的客户端代码必须位于以client结尾的包中,您的服务器代码必须位于以server结尾的包中。projectCreator还是applicationCreator无法配置为其他方式,因为这通常是GWTShell还是GWTCompiler期望您的代码所在的位置。稍后,我们将探讨一些重新组织源代码和调整运行配置以使其更灵活的方法。

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

使用“导入”->“常规”->“将现有项目导入工作区”。

第 2 步:完成 Google 教程并开发 Java 源代码

确保您继续完成“基础知识”并继续解决“使用远程过程调用”部分。远程过程调用部分将确保您的股票价格更新代码在网络服务器上运行,该服务器将每 5 秒动态更新网页。这提供了一个简单而强大的演示,展示了 Ajax 的功能以及 GWT 在 Java 代码中抽象该行为的方式。您最终应该会得到一个如下所示的项目

如果您不想经历开发示例代码的过程,您可以在此处下载我的初始项目的压缩副本。要运行我的项目,您需要完成以下步骤

- 解压缩并导入项目(“导入”->“将现有项目导入工作区”)- 定义一个GWT_ROOT_INSTALL变量,如上面的背景中所述 - 修改StockWatcher GWTShell.launch中包含的运行配置,或使用以下值创建一个新的运行配置

- 右键单击 StockWatcher 项目 ->“运行方式”->“运行配置” - 对于“主类”,输入com.google.gwt.dev.GWTShell- 在“程序参数”中,输入-out www com.google.gwt.sample.stockwatcher.StockWatcher/StockWatcher.html- 仅在 Mac OS X 上,在“VM 参数”中,输入-XstartOnFirstThread- 在“类路径”->“用户条目”中

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

请注意,将/src文件夹添加到类路径是 GWTShell 的要求,因为它需要类路径上包含元数据,例如其 .xml 文件。

第 3 步:在托管模式下运行 - 检查它是否有效!

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

在选中 StockWatcher 项目的情况下单击“运行”按钮,或选择您在第 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 步所述,GWTShell还是GWTCompiler要求您的源代码位于名为/src的子目录中。这限制了您的 WAR 项目与 Maven 和 Ant 等工具集成的便利性。

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

虽然这可能看起来是不必要的额外工作,但随着我们采用不同的方法,您会看到早期拆分代码可以使其更容易地部署为共享服务。

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

如果您工作区中还没有 dm Server 实例,则需要点击“目标运行时”文本字段旁边的“新建”按钮并选择“创建新的本地服务器”。请注意,我还选择了src/main/java还是src/main/webapp分别作为“Java 源目录”和“内容目录”。您可以使用默认值,但建议使用这些路径,因为它们与 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包中的类(属性 -> Java 构建路径 -> 项目 -> 添加...)。

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

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

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

- 右键单击 StockWatcher 项目 ->“运行方式”->“运行配置”并创建一个新配置 - 对于“主类”,输入com.google.gwt.dev.GWTCompiler- 在“程序参数”中,输入-out <您的工作区路径>/StockWatcherWar/src/main/webapp com.google.gwt.sample.stockwatcher.StockWatcher- 仅在 Mac OS X 上,在“VM 参数”中,输入-XstartOnFirstThread- 在“类路径”->“用户条目”中

- 添加gwt-dev-<os>.jar(例如gwt-dev-mac.jar)- 添加 StockWatcher 项目/src文件夹和 StockWatcherWar/src/main/java文件夹,使用“高级”->“添加文件夹”

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

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

第 6 步:配置 WAR 项目

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

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

- 添加 Web 模块依赖项gwt-servlet.jar(“属性”->“Java EE 模块依赖项”->“添加外部 Jar”)。请注意,此模块依赖于javax.servletAPI。 - 根据 Google 的说明修改web.xml文件。同时添加StockWatcher.html<welcome-file-list>中,以便在部署时自动显示(尽管在 Eclipse 中部署时这并不总是有效,因为浏览器窗口通常在服务器完全初始化之前打开)。

如果您遇到问题,请查看我从第 4 步下载的压缩项目。

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

现在我们已经创建了全新的 WAR 项目,让我们将其部署到 STS 中的 dm Server。只需右键单击 StockWatcherWar 项目并选择“运行方式”->“在服务器上运行”。如果欢迎页面没有自动出现,请刷新页面或手动将/StockWatcher.html添加到 URL 中。

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

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

的构建路径。假设这一切都奏效了,现在让我们将 WAR 打包并部署到工具之外。

第 8 步:在 STS 之外导出和部署

首先,我们需要将我们的项目导出为 WAR 文件。这通过右键单击 StockWatcherWar ->“导出”->“Web”->“WAR 文件”来实现。如果您想知道“覆盖现有文件”复选框在哪里,那是因为 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

https://:8080/admin/web/applications/list.htm

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

您现在应该会看到以下内容

在“应用程序位置”文本字段中浏览您导出的 WAR 文件,然后单击上传。这将上传并部署 WAR 文件,该文件随后应显示在“已部署应用程序”中

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

[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 中提取出来,并将其转换为一个捆绑包,该捆绑包可由服务器中运行的所有 GWT 应用程序共享。我们还将稍微深入了解内部,看看我们的 OSGi 捆绑包如何交互。

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

领先一步

VMware 提供培训和认证,助您加速进步。

了解更多

获得支持

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支持和二进制文件,只需一份简单的订阅。

了解更多

即将举行的活动

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

查看所有