在 SpringSource dm Server 中部署 GWT 应用 - 第 3 部分

技术 | Ben Corrie | 2008 年 12 月 19 日 | ...

引言

这是三篇系列博客中的最后一篇,描述了在 SpringSource dm Server™ 中构建和部署 GWT 应用的分步方法。第一篇博客介绍了从 GWT 示例应用创建简单 WAR 文件的过程,第二篇博客将 GWT 依赖项转换为可在多个应用之间共享的 OSGi 包。本篇最终博客将使用 Spring Dynamic Modules 进一步将我们的 GWT 示例模块化为 OSGi 服务。这应该清楚地展示 OSGi 模块化的优势:能够在运行时移除和替换服务,无缝管理多个版本的包,以及使用 dm Server 进行部署和管理是多么简单。

这是该系列中唯一一篇实际使用了 Spring Framework 的博客。Spring 用于配置 Spring Dynamic Modules 以及发布和消费 OSGi 服务。它还展示了一种连接 Spring 管理的 bean 与 GWT 远程处理的方式。然而,我很清楚 Spring/GWT 集成本身就是一个重要主题,所以我在此有意只提供一个简单的解决方案。

关于 GWT StockWatcher 示例及其我正在使用的软件的背景信息,请参阅第 1 部分

另请注意,您可以跳过所有这些繁琐的说明,直接查看底部的下载汇总。

快速回顾

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

第 2 部分中,我们从 WAR 文件中移除了 GWT 依赖项,并将它们转换为一个 OSGi 包,该包被安装到 dm Server 的仓库中。完成此操作后,我们就可以部署任意数量使用 GWT 远程处理的应用,而无需在 WAR 中包含任何 GWT 依赖项。

在本最终部分中,我们将使用 Spring Dynamic Modules 进一步模块化应用。您可能会问一个问题……为什么?这不是一个坏问题——没有人愿意为了模块化而使代码不必要地复杂化。在决定共享服务方法是否有帮助时,可以将其归结为几个简单的问题:

- 应用的任何部分是否可能需要被其他应用使用? - 应用中的不同组件是否会以不同的速度演变? - 是否可能需要维护同一组件的多个并发版本? - 是否希望能够在应用运行时部署组件的更改?

看看我们的 Stockwatcher 应用,它目前仅限于一个股市。我们知道世界各地有许多不同的市场,为了使其更灵活,使其能够访问不同的市场肯定是有意义的,所以这就是我们要做的——将我们的股市转换为共享服务。一个包将包含一个共享 API,该 API 定义了市场可以做什么。其他包可以是该 API 的实现——也许一个是伦敦市场,一个是纽约市场。然后我们将能够部署我们想要的市场,启动、停止、取消部署和替换它——所有这些都在运行时进行。

我意识到将单个 WAR 文件转换为共享服务的过程可能比从零开始以模块化方式设计更为常见,因此本博客将进一步基于我们在第 2 部分中完成的工作,而不是从头开始。您可以在此处下载第 2 部分的 Eclipse 项目,在此处下载第 3 部分所有工作完成后的项目(如果下载,需要定义 GWT_ROOT_INSTALL classpath 变量)。希望我在早期博客中关于划分源代码的一些建议最终会变得有意义!

步骤 1:创建 StockService API 包

为了创建伦敦和纽约 StockWatcherService 实现包,我们将需要一个它们的公共 API。显然,模块化公共代码是良好的实践,但需要一个单独的 API 包还有一个更重要的原因。如果您想在 dm Server 中取消部署正在运行的应用中的包,可以安全地移除实现服务的代码,但不能移除剩余代码所依赖的任何接口。因此,将我们的服务接口和公共代码放入 API 包中是有意义的,该包将是其他包的依赖项。

要在 Eclipse 中创建一个简单的包项目,右键单击并选择 New->Other->SpringSource dm Server->Bundle Project。这将为您创建一个骨架MANIFEST.MF以便开始使用。我们无需将其设为 Spring Dynamic Module,因为它唯一的目的是提供 API,并且不会包含自己的任何 bean 实例,因此普通包即可。

- 将项目名称指定为 StockWatcherServiceAPI - 如果您愿意,可以通过单击 Project Layout 中的 Configure Default... 链接来配置源目录。为保持一致性,我将其设置为src/main/java- 将包名称和符号名称设置为com.google.gwt.sample.stockwatcher.client.api版本保留为1.0.0- 模块类型应为None目标运行时应为您的 dm Server 实例。如果无法选择此选项,需要单击新建并创建一个。 - 现在可以单击完成,应该会看到新的包项目以及生成的MANIFEST.MF.

下一步是移动 API 代码到新项目中。将整个com.google.gwt.sample.stockwatcher.client.api包从 StockWatcherWar 项目拖放到新的包项目中。这是客户端和服务器共享的所有代码。它应该包含StockPriceService接口以及StockPriceDelistedException类。如果成功,几乎所有东西都会损坏!

接下来,考虑一下我们需要从新包中导出什么。在这种情况下很简单——一个包中的 API。在MANIFEST.MF编辑器的 Runtime 选项卡中,将该包添加到 Exported Packages 列表中并保存。

现在需要考虑 API 代码需要哪些依赖项,换句话说,为什么它不再构建了。显然,我们在第 2 部分中创建的 GWT 包是一个好的开始。在 Dependencies 选项卡中,将 com.google.gwt 包添加到 Import Bundle 列表中(如果未列出,可能不在 dm Server 仓库中,这在第 2 部分中解释了)并保存。这应该会修复新项目中的所有构建问题,但其他项目应该仍然损坏。暂时忽略这一点,因为还有更多重构工作要做。

此时,StockWatcherServiceAPI 项目应该看起来像这样

它的MANIFEST.MF应该看起来像这样

步骤 2:创建 StockPriceService 服务包

创建了一个包含公共代码的 API 包,从中可以创建多个服务实现,现在创建一个实现。从伦敦开始。

使用步骤 1 中的说明创建一个新的包项目,命名为 "StockWatcherServiceLondon",并给它一个包名称 com.google.gwt.sample.stockwatcher.service.london。

所以我们来考虑一下这个包需要什么。它需要实现伦敦股市服务的代码,以及一种将该服务导出到 OSGi 注册中心作为共享服务的方式。第一部分是一个简单的重构工作,因为我们已经有一些可以重用的服务代码。对于第二部分,将包设为 Spring Dynamic Module 将是最简单的方法,因为它使得使用 Spring bean 发布和消费 OSGi 服务非常简单。

首先。回头看看StockPriceServiceImpl.java中的服务实现。会看到StockPriceService代码与RemoteServiceServlet绑定。servlet 需要保留才能使远程处理工作,但我们需要提取实现代码并用它来创建共享服务。在第 4 部分中,需要调整 servlet 来消费我们创建的服务。

所以,复制com.google.gwt.sample.stockwatcher.server包从 StockWatcherWar 项目,并粘贴到 StockWatcherServiceLondon 的src/main/java中。现在应该有一个StockPriceServiceImpl.java的副本,可以进行重构。

删除extends RemoteServiceServletRemoteServiceServletimportSerialVersionUID

字段,因为这些现在都不再需要了。保存更改时,会看到需要导入一些依赖项,特别是步骤 1 中创建的 API 包。MANIFEST.MF编辑com.google.gwt.sample.stockwatcher.client.api以添加 Import Package 来导入MANIFEST.MF。保存时,应该会看到清单文件中出现错误,说无法解析该包。我们做错了什么?!问题在于,当 Eclipse 中的包项目之间存在导入和导出时,需要告诉工具允许项目共享引用。右键单击 StockWatcherServiceLondon,选择 Properties->Project References。勾选 StockWatcherServiceAPI 的复选框,然后单击 OK。然后需要假编辑

以使更改生效。现在应该看到 StockWatcherServiceAPI 列为 Bundle Dependency。让我澄清一点,一旦包从 Eclipse 导出,就无需执行此额外步骤——仅当需要在它们只是项目时创建包之间的依赖项时才需要这样做。MANIFEST.MF应该还有一个问题需要解决。虽然 com..client.api 包导入了 com.google.gwt 包,但该导入对于该包是私有的。任何导入 com..client.api 包的包都不继承此依赖项——必须明确指定。因此,在中,为 com.google.gwt 包添加一个Import-BundleStockPriceServiceImpl.java并保存。如果仍然在

中看到问题,可能需要尝试对其进行假编辑,否则您就做错了什么。

太棒了!现在我们已经完成了一半的共享服务创建工作。它目前应该看起来像这样下一步是将 StockPriceServiceLondon 转换为 OSGi 服务。我们将使用 Spring Dynamic Modules 来完成。Spring Dynamic Module 的原理很简单——在/META-INF/spring

文件夹中提供 Spring 配置文件,部署包时会为您创建一个 ApplicationContext。这是一种极好且非常简单的方式,可以将 Spring 管理的 bean 导出为 OSGi 服务。因此,在/META-INF中创建/spring中创建文件夹(右键单击因此,在并选择 新建 -> 文件夹)。然后右键单击新的文件夹,选择 新建 -> Spring Bean Definition。可以随意命名,但在我的示例中命名为serviceLondon-config.xml。输入名称并单击完成。现在需要将StockPriceServiceImpl

    <bean id="stockPrices"
        class="com.google.gwt.sample.stockwatcher.server.StockPriceServiceImpl"/>

定义为 Spring bean,以便在部署包时创建它的一个实例。如果熟悉 Spring,这应该很容易。如果不熟悉,需要插入以下 XML

    <osgi:service
        interface="com.google.gwt.sample.stockwatcher.client.api.StockPriceService"
        ref="stockPrices"/>

最后,需要将此 bean 导出为 OSGi 服务。可以在同一个配置文件中完成,但将 OSGi 依赖项分开是良好的实践。因此创建另一个 Spring Bean Definition,命名为 osgi-config.xml,这次单击下一步并勾选 osgi 命名空间复选框,然后单击完成。要将 bean 导出为 OSGi 服务,请插入以下 XML

就是这样!现在我们有一个创建共享服务的包。在继续之前,测试一下是个明智的主意,以确保它按预期运行。

步骤 3:测试共享服务包

我将在此描述两种测试方法:快速而粗糙的方法和完善文档的自动化 JUnit 方法。有人可能会说这应该是一篇单独的博客文章,但我认为这是一个足够重要的话题,因此在此详细介绍。

快速而粗糙的测试

快速而粗糙的方法是临时创建一个另一个 Spring Dynamic Module,它将消费该服务,将其注入到测试类中,然后只记录输出。这是确保服务工作正常的好方法,但显然它没有断言任何内容,也无法在测试框架中运行。下一步是将 StockPriceServiceLondon 转换为 OSGi 服务。我们将使用 Spring Dynamic Modules 来完成。Spring Dynamic Module 的原理很简单——在我们已经构建了一个 Spring Dynamic Module,因此对于这个新的 TestConsumer 模块,我只强调差异。模块需要导入 com.google.gwt.sample.stockwatcher.client.api 包(或 package),并且需要一些 Java 代码来调用服务客户端。在

文件夹中需要 2 个 spring 配置文件一个用于测试 bean(例如)

    <bean id="consumer" class="com.ben.consumer.Consumer">
        <constructor-arg ref="priceService"/>
    </bean>

testConsumer-config.xml),一个用于消费服务的<osgi:reference(例如)

    <osgi:reference id="priceService"
        interface="com.google.gwt.sample.stockwatcher.client.api.StockPriceService"/>

osgi-config.xml在 Java 代码中,只需调用service.getPrices(new String{"foo", "bar"})StockPrice并传入一些任意字符串,应该返回一个StockPrice对象的数组。如果想将输出记录到System.err.

,这会出现在 dm Server 的跟踪目录中<dm server install directory>/servicability/trace/<name of your test bundle>/trace.log要在 STS 中运行快速而粗糙的测试,需要启动 dm Server。然后,将整个 StockWatcherServiceAPI 项目拖放到服务器上。项目成功部署后,应该会收到类似如下的控制台消息

Deployment of 'com.google.gwt.sample.stockwatcher.client.api' version '1' completed。接下来,将整个 StockPriceServiceLondon 项目拖放到服务器上,并等待部署消息。如果这一切都初始化成功,将您的测试项目放到服务器上。如果您想让服务器每次都干净启动(清除旧的跟踪输出等),请在启动配置中添加

-Dcom.springsource.server.clean=true

VM 参数,可以通过双击服务器实例,选择 Open Launch Configuration 并单击 Arguments 选项卡来找到。

如果这不起作用并且您不确定原因,可以在此处下载我的整个 Eclipse 工作空间。自动化 JUnit OSGi 包测试可以在参考指南此处阅读有关 Spring Dynamic 模块自动化集成测试的支持。AbstractConfigurableBundleCreator 测试类将启动一个 OSGi 框架,加载所有必需的测试包,然后将测试代码构建为即时包并进行测试。如果您认为这可能听起来很复杂,那就对了。为了不让您感觉吃亏,亲爱的读者,我自己尝试了,必须诚实地说,设置它以使所有必需的依赖项工作起来有点痛苦。所以这是我的分步无痛指南,教您如何使其运行起来。

因此,开箱即用时,测试期望从本地 Maven 仓库获取其所有依赖项。可以配置测试使用其他类型的依赖管理,但为了简单起见(嘿!),我正在使用 Maven。首先,我安装了 m2eclipse,它通过添加http://m2eclipse.sonatype.org/update/作为更新站点(Help->Software Updates->Available Sites->Add Site)获得。建议取消选择可选的 Maven POM Editor,否则会收到一堆未满足的依赖项警告,并且无法安装。

创建一个新的 Java 项目,命名为 StockWatcherServiceTest(以src/main/javasrc作为源文件夹)。右键单击项目,选择 Maven->Enable Dependency Management 使项目支持 Maven。接下来,创建一个新包(在我的例子中是com.ben),并将 Spring DM 参考指南中的SimpleOSGiTest

代码复制到该包中的测试类(请注意,测试框架不允许使用默认包)。这个测试类将帮助我们进行健全性检查,确认依赖项都已正确设置。会注意到测试尚无法编译,因为我们尚未拥有它所需的依赖项。需要在pom.xml会注意到测试尚无法编译,因为我们尚未拥有它所需的依赖项。需要在文件中指定正确的依赖项。为了节省您数小时的捶胸顿足和诅咒,您可以在此处查看我的

pom.xml文件(包含在完整的工作空间下载中)。一旦依赖项工作正常,看看能否找出示例代码中的拼写错误,添加 Java import,现在应该有一个可以编译的测试类了。尝试运行测试:右键单击 -> 运行方式 -> JUnit Test。如果收到ClassNotFoundException,是因为测试在错误的位置查找.class文件。解决此问题的最简单方法是覆盖getRootPath()并返回

"file:./target/classes"

或 .class 文件生成的任何其他路径。希望现在会看到绿条,这至少证明了测试用例启动了 Equinox 框架并成功创建了即时包。现在可以为 StockWatcherServiceLondon 包创建合适的单元测试了。下一步是使测试依赖包正确加载和解析。为此,必需的包需要安装到本地 maven 仓库,并在测试用例中的

getTestBundlesNames()会注意到测试尚无法编译,因为我们尚未拥有它所需的依赖项。需要在方法中指定。会注意到测试尚无法编译,因为我们尚未拥有它所需的依赖项。需要在先处理 Maven:之前创建的MANIFEST.MFpom.xml文件应该已经下载了外部依赖项,但我们需要手动将 com..client.api、com..service.london 和 com.google.gwt 包添加到 maven 仓库。我通过对工作空间中的项目进行 Maven 化并为每个项目创建一个pom.xml会注意到测试尚无法编译,因为我们尚未拥有它所需的依赖项。需要在文件来完成此操作。这里有几个陷阱。首先,要让 Maven 识别会注意到测试尚无法编译,因为我们尚未拥有它所需的依赖项。需要在 manifest中,为 com.google.gwt 包添加一个文件,必须在pom.xml中配置maven-jar-plugin并指向文件位置。在此处查看我的pom.xml。其次,我发现 Spring dm Server 专有的

manifest希望现在会看到绿条,这至少证明了测试用例启动了 Equinox 框架并成功创建了即时包。现在可以为 StockWatcherServiceLondon 包创建合适的单元测试了。条目不起作用,所以我必须修改两个项目,转而使用多个

Import-Package文件(包含在完整的工作空间下载中)。一旦依赖项工作正常,看看能否找出示例代码中的拼写错误,添加 Java import,现在应该有一个可以编译的测试类了。条目。进行这些更改后,打开命令提示符,切换到项目目录并输入mvn install。这将构建插件并安装到本地 maven 仓库。要安装我们在第 2 部分构建的 gwt 插件,我使用了以下命令行mvn install:install-file -DgroupId=com.google.gwt -DartifactId=com.google.gwt -Dversion=1.5.3 -Dpackaging=maven-plugin -Dfile=<location of jar file>.

。此时值得检查一下插件是否正确构建,可以通过解压仓库中的 jar 文件并检查清单文件是否正常来完成。),一个用于消费服务的一旦所有测试包构建并安装到仓库中,需要在测试用例的(例如method中指定它们。语法在参考文档中描述,我指定了 4 个包:com..client.api、com..service.london、com.google.gwt 和 javax.servlet。希望此时,您将能够在没有任何实际断言的情况下运行测试,并且应该能够成功地安装和启动所有测试包而没有问题。如果不起作用,一个有用的调试工具是启用 Equinox telnet 控制台,并用它来检查预期的导入和导出看起来是否都正确。如果收到因此,在UnsatisfiedLinkError

,它们可能不正确。启用控制台的方法是覆盖createPlatform()并调用

System.setProperty("osgi.console", "9000")

一旦所有包都正确解析和启动,您终于可以编写断言了!我们需要消费由 com..service.london 包导出的服务。将上面快速而粗糙示例中的

行复制到 XML 文件中,然后将此添加到测试用例中的

getConfigLocations()

方法,该方法返回一个配置文件名的 String 数组。在这种特殊情况下,我们将使其成为一个普通的 OSGi 包,而不是 Spring Dynamic Module,因此无需将文件放到),一个用于消费服务的/META-INF/spring中创建文件夹中。(例如在集成测试中,Spring 将自动装配所有 Spring 管理的 bean 到存在适当 setter 方法的测试用例中,因此添加),一个用于消费服务的setStockPriceService(StockPriceService s)因此,在方法将把 OSGi 服务注入到测试类中。一旦获得了服务的引用,就可以开始对其进行断言了……终于!现在,我意识到这是一个非常冗长的描述,而最终只是一个简单的概念。坦白地说,理解配置的最佳方法是查看我的 Eclipse 工作空间此处。我详细描述它是因为看到一个工作示例是一回事,而理解实现过程和陷阱是另一回事。然而,一旦设置好,这是一种极其强大的方法,可以以自动化方式集成测试包服务。步骤 4:消费共享服务

在步骤 2 中,我们创建了一个 API 包和一个共享服务包。现在需要重构我们的其他项目以在编译时和运行时与这些包一起工作。在步骤 2 结束时,您将破坏 StockWatcherWar 和 StockWatcher 项目中的一些依赖项。先修复这些。

    <context-param>
        <param-name>contextClass</param-name>
        <param-value>com.springsource.server.web.dm.ServerOsgiBundleXmlWebApplicationContext</param-value>
    </context-param>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/META-INF/*.xml</param-value>
    </context-param>

从 StockWatcher 开始,它损坏了,因为我们移除了它所依赖的 WAR 项目中的 API。更改其构建时依赖项,使其引用 StockWatcherServiceAPI 项目(右键单击 -> 构建路径 -> 配置构建路径 -> 项目)。此项目没有运行时依赖项,因此需要做的就是这些。

StockWatcherWar 现在需要进行一些修改来消费我们在步骤 2 中创建的 OSGi 服务。当前,它仍然包含我们在步骤 2 中复制到服务包中的服务代码,所以一项工作是移除此代码,并用一个转而委托给 OSGi 服务的调用来替换它。然而,这意味着我们需要以某种方式将服务包的引用传递到类中……这也意味着我们实际上需要从某个地方获取它的一个实例。让我们进一步分析。。输入名称并单击完成。现在需要将好的,我们已经知道如何获取服务的引用,因为我们在上面的测试方法中做到了:创建一个 spring 配置文件并添加一个<osgi:referencepom.xml标签。所以我们先做这个。在/META-INF中创建一个新的 Spring Bean Definition(右键单击 -> 新建 -> Spring Bean Definition),随意命名(例如osgi-service-references.xml),并确保勾选 osgi 命名空间复选框以包含 schema。添加步骤 3 中的<osgi:reference

示例代码,现在您有了一个用于消费 OSGi 服务的 Spring 配置文件。这个配置文件是否应该放到。输入名称并单击完成。现在需要将/META-INF/spring子目录中,使其成为 Spring Dynamic Module?正确答案是否定的。我们需要用它来引导一个特定类型的 ApplicationContext,该 ApplicationContext 在web.xml中定义,因此无需为我们自动创建另一个。.

顺便说一下,编辑 web.xml 并添加以下行。输入名称并单击完成。现在需要将这将引导一个 dm Server ApplicationContext,并使用 /META-INF 中的所有 xml 文件来配置它。中,为 com.google.gwt 包添加一个接下来,我们需要弄清楚如何将这个 Spring 管理的服务实例传递给

StockPriceServiceImpl),并确保勾选 osgi 命名空间复选框以包含 schema。添加步骤 3 中的类,换句话说,一种连接 Spring 和 servlet 世界的方法。一种方法是从中创建ServletContext查找ApplicationContext并调用其):

    <bean id="myFilter" class="com.google.gwt.sample.stockwatcher.server.StockPriceServiceFilter">
        <constructor-arg ref="priceService"/>
    </bean>

getBean()方法。这不太好,因为它要求我们将 bean 名称硬编码到服务代码中,并依赖于依赖查找。一种更清晰的机制是使用 Spring 管理的ServletFilter),并确保勾选 osgi 命名空间复选框以包含 schema。添加步骤 3 中的,将服务实例注入其中,然后使用静态常量进行查找,将其传递给 servlet。这就是我在这里实现的现在,我意识到这是一个非常冗长的描述,而最终只是一个简单的概念。坦白地说,理解配置的最佳方法是查看我的 Eclipse 工作空间此处。我详细描述它是因为看到一个工作示例是一回事,而理解实现过程和陷阱是另一回事。然而,一旦设置好,这是一种极其强大的方法,可以以自动化方式集成测试包服务。这个类应该和现在,我意识到这是一个非常冗长的描述,而最终只是一个简单的概念。坦白地说,理解配置的最佳方法是查看我的 Eclipse 工作空间此处。我详细描述它是因为看到一个工作示例是一回事,而理解实现过程和陷阱是另一回事。然而,一旦设置好,这是一种极其强大的方法,可以以自动化方式集成测试包服务。StockPriceServiceImpl),并确保勾选 osgi 命名空间复选框以包含 schema。添加步骤 3 中的类一起创建在 StockWatcherWar 项目中。另外,别忘了在doFilter())

    <filter>
        <filter-name>myFilter</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
        <init-param>
            <param-name>targetFilterLifecycle</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>

    <filter-mapping>
        <filter-name>myFilter</filter-name>
        <servlet-name>StockService</servlet-name>
    </filter-mapping>

中委托给方法。这不太好,因为它要求我们将 bean 名称硬编码到服务代码中,并依赖于依赖查找。一种更清晰的机制是使用 Spring 管理的FilterChain现在,我意识到这是一个非常冗长的描述,而最终只是一个简单的概念。坦白地说,理解配置的最佳方法是查看我的 Eclipse 工作空间此处。我详细描述它是因为看到一个工作示例是一回事,而理解实现过程和陷阱是另一回事。然而,一旦设置好,这是一种极其强大的方法,可以以自动化方式集成测试包服务。。如果您一直仔细按照说明操作,由于步骤 1 中的重构,这个类和

StockPriceServiceImpl。输入名称并单击完成。现在需要将都无法编译。要修复这个问题,需要将 StockWatcherServiceAPI 添加为 StockWatcherWar 的项目引用(右键单击 -> 属性 -> 项目引用),然后将 com.google.gwt.sample.stockwatcher.client.api 添加到

Import-Package

列表中。进行此更改后,代码现在应该可以编译了。

现在有了 servlet 和 ApplicationContext 之间的桥梁,我们需要做的就是创建

GwtRpcStockServiceFilter

的实例,并将服务注入其中。在/META-INF中创建另一个 spring bean 定义,随意命名(例如stockwatcher-config.xml)。将以下配置复制到其中(假设您使用的 OSGi 服务的 bean 名称是中,为 com.google.gwt 包添加一个priceService

)。

最后,我们需要一个叫做

DelegatingFilterProxy

的小魔法。这个类将所有传入和传出的 servlet 请求委托给 Spring 管理的

ServletFilter

,并在

- MANIFEST.MFweb.xml文件夹,选择 新建 -> Spring Bean Definition。可以随意命名,但在我的示例中命名为中定义。将此代码复制到您的StockPriceServiceImpl.javaweb.xml

中(它假设您的

filter

的 bean 名称是

myFilter)。拼图的碎片终于组合在一起了。会看到,在上面的代码中,我们将

filter

映射到了 StockService servlet。web.xml 配置现在完成了。

确定了部署模式后,您可以使用管理控制台上传文件,或者将文件复制到<dm Server 安装目录>/pickup目录中。首次执行此操作时,服务器需要已处于运行状态,并且您应按正确的顺序将 bundle 复制到目录中。dm Server 会记住此顺序,以便您下次启动服务器时使用。使用此机制的优势在于,只需将单个 bundle 移入或移出此目录,即可对其进行热部署或取消部署。

下载摘要

我意识到之前我在博客中分散放置了下载链接,所以我想在这里做一个总结。另外,对于将小文件压缩成 zip 包,我感到抱歉,但出于安全原因,博客工具不允许我直接上传原始的 XML 或 Java 文件。希望您使用愉快!
  • 整个第三部分的 workspace 项目,包括两种类型的测试机制,请点击这里

  • 可在此处下载导出的 bundle:点击这里

  • 可在此处下载项目的 PAR 文件(包含伦敦市场):点击这里

获取 Spring 新闻通讯

通过 Spring 新闻通讯保持联系

订阅

保持领先

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

了解更多

获取支持

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

了解更多

即将举行的活动

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

查看全部