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

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

介绍

这是由三篇博客组成的系列文章中的第二篇,该系列文章逐步描述了在SpringSource dm Server™中构建和部署GWT应用程序的方法。第一篇博客介绍了从GWT示例应用程序创建简单WAR文件的过程。这篇博客将介绍如何将我们在第1部分中创建的WAR文件转换为“共享库”WAR。这意味着我们将把应用程序的GWT依赖项外部化到一个OSGi捆绑包中,以便任何数量的GWT应用程序都可以共享它。您可以将其视为使用GWT远程处理功能扩展我们的dm Server。

第1部分中所述,在这篇博客文章中我没有使用Spring框架,而是专注于SpringSource dm Server™SpringSource Tool Suite来部署“纯”GWT。

另请参阅第1部分,了解GWT StockWatcher示例和我的软件使用背景。

快速回顾

第1部分中,我们从头开始构建了GWT StockWatcher示例应用程序作为Eclipse项目,然后将代码生成到一个动态Web项目中,然后将其部署到dm Server中。最后,我们将动态Web项目导出为WAR文件,并将其部署在STS之外。

此处描述的逐步方法将基于我们在第1部分中所做的工作,而不是重新开始。我们在第1部分中现在要更改的唯一内容是删除对gwt-servlet.jar库的显式依赖。

步骤1:将我们的GWT依赖项转换为OSGi捆绑包

首先,再补充一些背景知识。“共享库”方法的整个概念是使用dm Server中OSGi捆绑包之间的显式导入和导出创建依赖项映射。对于像我们的StockWatcher示例这样的小型WAR,这主要只是一个有趣的学术练习。但是,鉴于许多商业Web项目都以包含数十甚至数百个依赖jar文件的巨大WAR文件形式发布,将这些依赖项分解为可共享的资源不仅从占用空间的角度来看是有意义的,而且还使应用程序的打包、版本控制和维护变得明显更容易。

好消息是,大部分创建这些依赖项的工作已经为您完成。 SpringSource企业捆绑包存储库包含大多数常用库的“捆绑”版本。但是,在撰写本文时,我们的GWT依赖项是您必须自己转换为捆绑包的库示例。对我们来说幸运的是,Eclipse 3.4使此过程非常简单。

- 在项目资源管理器中单击鼠标右键,然后选择“新建”->“其他”->“插件开发”->“从现有Jar存档创建插件”。- 单击“添加外部”并浏览到gwt-servlet.jar。- 单击“下一步”并将项目命名为“com.google.gwt”。- 设置插件版本以反映GWT版本,在本例中为1.5.3。- 选择“分析库内容并添加依赖项”- 选择Equinox OSGi框架

单击“完成”,无需切换到插件开发透视图。我们只需要再次导出我们的捆绑包。

您现在应该看到生成的MANIFEST.MF文件的概述,这是定义捆绑包依赖项的位置。您将在“运行时”选项卡中看到,该工具已将所有com.google.gwt..包添加为导出。您还将在“依赖项”选项卡中看到,它已经确定此捆绑包需要几个javax.servlet..包和一个junit包。

我们现在将删除JUnit依赖项,因为它在dm Server中默认情况下将无法解析。当然,如果需要,我们可以向dm Server添加一个JUnit捆绑包以满足依赖关系,或者我们可以通过添加required:=optional来使依赖关系可选。选择junit.framework包,单击“删除”,然后保存。

值得指出的是,这是一种将JAR文件转换为捆绑包的粗略方法,不能保证在所有情况下都能正常工作。一方面,我们可能不希望导出所有包。但是,更重要的是,可能存在一两个源代码级别的问题,这些问题在OSGi中可能无法正常工作,例如使用Class.forName()。如有疑问,请始终首先访问SpringSource企业捆绑包存储库,而不是尝试自己创建。

最后,我们需要将我们的插件项目导出为OSGi捆绑包。选择“导出”->“插件开发”->“可部署的插件和片段”。选择一个方便的位置作为输出目录。

我们现在应该在<导出路径>/plugins/com.google.gwt_1.5.3.jar中看到一个文件。下一步是重命名该文件,使其与dm Server中其他命名捆绑包的格式一致:只需将下划线更改为短横线com.google.gwt-1.5.3.jar。如果不进行此更改,当前版本的STS将无法识别捆绑包版本。如果要跳过此步骤,可以在此处下载。

最后,将捆绑包复制到dm Server捆绑包存储库<dm Server安装根目录>/repository/bundles/usr。此处的任何捆绑包都可以作为dm Server中其他捆绑包的依赖项,但重要的是,它也将在STS中显示为依赖项,正如我们将在下一步中看到的那样。

此时,您可以从工作区中删除com.google.gwt项目,因为它已经完成了其目的。

步骤2:将我们的WAR项目迁移到新的OSGi捆绑包

希望您现在应该有一个dm Server安装,其中包含com.google.gwt-1.5.3.jar在其存储库中。

下一步是破坏我们的应用程序!

右键单击StockWatcherWar,选择“属性”->“Java EE模块依赖项”,取消选择gwt-server.jar文件,然后单击“确定”。我们现在已经删除了WAR对GWT的显式依赖,并为自己制造了一些新问题,其中大部分是编译器错误。

因此,我们需要将我们的动态Web项目转换为dm Server捆绑包,以便它可以从我们新创建的GWT捆绑包中显式导入其所需的依赖项。为此,请右键单击StockWatcherWar,然后选择“Spring工具”->“添加OSGi捆绑包项目性质”。您应该注意到,该项目现在带有非常重要的“S”符号,并且MANIFEST.MF的字符也已更改

它已损坏,因为它看起来不像捆绑包清单。让我们添加一些合理的默认值(您可以剪切并粘贴以下内容,或者使用选项卡中的字段)。请注意,您也可以在编辑器中使用ctrl-space来提示有效的选项。

Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: com.google.sample.stockwatcher Bundle-SymbolicName: com.google.sample.stockwatcher Bundle-Version: 1.0.0 Bundle-Description: 共享库StockWatcher演示

因此,这修复了一个问题,即我们的捆绑包清单现在看起来很合理。但是,我们尚未定义对GWT捆绑包的依赖关系,因此我们仍然有很多编译器错误。

选择“依赖项”选项卡,然后单击“添加”。在顶部,您应该看到一个com.google.gwt捆绑包已神奇地出现。现在,重要的是要理解,此列表中出现的GWT捆绑包与我们在步骤1中创建的插件项目无关。如果从工作区中删除该项目,该捆绑包仍将出现。它之所以有效,是因为dm Server安装被设置为项目的运行时,因此该工具正在dm Server的存储库中查找您可能想要导入的任何捆绑包。如果这不起作用,则GWT捆绑包要么没有复制到正确的位置,要么WAR项目的运行时没有设置为dm Server。在“属性”->“目标运行时”中检查后者。

接下来,选择GWT捆绑包,单击“确定”,然后保存清单。您现在应该看到GWT捆绑包已添加到名为“捆绑包依赖项”的新类路径元素中。

您现在应该注意到大部分错误都已解决,但仍有一些错误未解决。这是因为我们的GWT捆绑包依赖于javax.servletAPI,并且在我们拥有这些类之前,类型层次结构是不完整的。

那么,当我们只有gwt-servlet.jar我们的构建路径中有什么?在我们进行更改之前,我们的WAR文件会获取构建路径上的所有内容,其中包括dm Server目标运行时提供的所有JAR文件。但是,您可能已经注意到,当我们添加OSGi Bundle项目特性时,构建路径上的dm Server JAR文件消失了。这是因为,通过成为一个OSGi bundle,我们进入了一个不同的依赖关系世界,在这个世界中必须显式声明导入和导出。

声明我们对javax.servletAPI的依赖很简单,只需导入另一个bundle即可。您将在列表中看到它作为com.springsource.javax.servlet。添加这两个bundle后,保存清单,您现在应该看到所有错误都已解决。呼!

如果我们现在导航到MANIFEST.MF选项卡,我们可以看到我们所有按钮点击的效果:清单中有一个绿色的“Import-Bundle”条目。请注意,我们也可以在“Import-Bundle”之后使用ctrl-space,它会建议所有可能的导入。

如果您想查看我的项目,可以下载压缩后的副本此处。它包括在托管模式下使用嵌入式Tomcat启动、在托管模式下使用dm Server启动以及启动GWT编译器的运行时配置。请注意,托管模式下使用嵌入式Tomcat可以正常工作,无需修改bundle WAR项目。这是因为javax.servletdm Server中的包不再位于构建路径中。要使用我的项目,您需要GWT_ROOT_INSTALL变量,并且您可能需要选择您的dm Server目标运行时实例,如第一部分中所述。

步骤3:部署到dm Server

部署我们的“共享库”应用程序的步骤与第一部分中的步骤7和8完全相同,因此无需再次详细介绍。当然,关键的区别在于我们已成功地将依赖项分解成一个库,该库可以被多个GWT应用程序共享。如果您下载我的StockWatcher共享库WAR,您会发现它现在是290k而不是890k。

只是为了好玩,让我们仔细看看内部,看看我们的bundle是如何交互的。

dm Server启动时,会通知您可以使用telnet客户端访问其OSGi控制台。

[2008-10-27 16:48:04.266] main                     <SPOF0001I> OSGi telnet控制台可在端口2401上访问。

让我们打开一个终端窗口,看看我们能找到什么。

> telnet localhost 2401 Trying ::1... Connected to localhost. Escape character is '^]'.

osgi>

您可以通过键入help来获取Equinox控制台可用的命令列表。还有一篇关于它的有用的DeveloperWorks文章,您可以在这里阅读。

键入ss会给我们一个所有正在运行的插件的列表。

osgi> ss

框架已启动。

id    状态       Bundle . . . . 73    ACTIVE      com.google.sample.stockwatcher_1.0.0 74    ACTIVE      com.google.gwt_1.5.3

键入包 74会给我们GWT bundle导出所有包的列表。它显示StockWatcherWar bundle正在导入所有导出的包。这是我们使用“Import-Bundle”的结果。碰巧的是,我们的StockWatcherWar实际上只需要com.google.gwt.user.client.rpccom.google.gwt.user.server.rpc。如果我们想,我们可以通过使用“Import-Package”显式导入这些包来更具选择性。这在dm Server程序员指南中进行了描述。

file:////Users/bcorrie/dmServer-1.0.0/springsource-dm-server-1.0.0.RELEASE/work/com.springsource.server.deployer/Module/StockWatcherWar.war-0/StockWatcherWar.war [73] imports com.google.gwt.i18n.client.constants; version="0.0.0"<file:////Users/bcorrie/dmServer-1.0.0/springsource-dm-server-1.0.0.RELEASE/repository/bundles/usr/com.google.gwt-1.5.3.jar [74]>

步骤4:在共享库上部署其他GWT应用程序

值得注意的是,并非所有GWT应用程序都需要使用gwt-servlet.jar。只有使用某种远程调用的GWT应用程序才依赖于此库。Google在其发行版中提供许多示例应用程序,其中大部分生成到javascript和html中,因此无需Java代码即可部署。将这些示例转换为WAR文件很简单,只需将编译脚本运行到动态Web项目中,如第一部分步骤5中所述,然后创建一个合适的web.xml。

但是,GWT发行版中包含的一个确实使用了一些简单的远程调用的示例称为DynaTable。使用这些博客中描述的相同步骤和原则,我将此示例转换为共享库WAR文件。要查看我的操作,您可以下载压缩的项目WAR文件并查看。这非常简单地演示了在dm Server中运行多个应用程序的原则,这两个应用程序都共享我们创建的GWT bundle。

期待第三部分

在本系列的最后一篇博客中,我们将进一步模块化我们的StockWatcher示例,将它的服务抽象成可以热交换进出正在运行的服务器的bundle。

获取Spring时事通讯

与Spring时事通讯保持联系

订阅

领先一步

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

了解更多

获取支持

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

了解更多

即将举行的活动

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

查看全部