简介
OSGi 是一个面向 Java 的动态模块系统。OSGi Alliance(请参见 参考资料)发布了模块系统的规范。一些受欢迎的 OSGi 容器包括 Eclipse Equinox(请参见 参考资料)和 Apache Felix 等等(请参见 参考资料)。作为一种用于开发和部署模块化的、可重用的 Java 程序的框架,OSGi 呈现出强劲的发展势头。
OSGi 容器允许以 Jar 格式部署 Java 模块(OSGi 将其称为 “包”)。OSGi 的一个有趣的功能就是能够把一个服务包的多个版本部署到同一个容器中。所有部署到 OSGi 容器中的包在一个 JVM 中运行。如果一个服务的客户端位于这个 OSGi 容器的外部,那么这个服务包需要有分布式功能。Apache cxf-dosgi(请参见 参考资料)是一个新的服务框架,支持用于 OSGi 包的分布式功能。
当 Web 服务提供商开发了一个新版本的服务时,通常需要继续支持现有的客户机。因此,Web 服务提供商需要同时部署和维护多个版本的服务。OSGi 自然成为满足这一需求的出色选择。
自从 CXF 团队发布了一个叫作 cxf-dosgi(支持对 OSGi 包进行分布)的新的框架以来,我选择 Eclipse Equinox 作为 OSGi 的容器,并选择 Apache CXF 作为 Web 服务框架。通过使用这个框架,我们可以把 Web 服务作为 OSGi 包进行开发和部署。由于一个包的多个版本能够共存,因此人们可以同时部署和维护多个版本的 Web 服务。我将把 Apache Tomcat 作为一个 servlet 容器使用,用于部署客户机。
在本文中,我将描述开发 cxf-dosgi 服务包的详细方法以及如何在 OSGi 容器中进行部署,并使用一个简单的 Web 客户机(和 OSGi 容器运行在不同的 JVM 中)对其进行访问。我还将描述开发同一个服务的不同版本并把它部署到同一个 OSGi 容器中,以及演示该服务的两个不同版本能够共存并为多个类型的客户机服务。
先决条件
首先下载并安装 Eclipse 3.5(Galileo)。Eclipse 3.5 包含了一个叫作 Equinox(请参见 参考资料)的 OSGi 框架
然后下载 cxf-dosgi 单包发行版和 osgi compendium 包。下载这两个包并保存到本地的同一个目录中。请参见下面的 参考资料,以获取下载链接。
下载并安装 Apache Tomcat 5.5.9。我们将使用在 OSGi 容器(Eclipse)外部的 servlet 容器,用来安装和运行我们的服务客户机。
准备 OSGi 容器
在开发一个分布式服务包之前,首先启动容器并把 cxf-dosgi 注册为服务提供商 enabler,从而为 OSGi 容器做准备。
使用一个空的工作空间启动 Eclipse 3.5。把 Perspective 设置为 “Plug-In Development”。一个 Eclipse 插件基本上就是一个 OSGi 包。
接下来使用菜单选项导入 cxf-dosgi osgi compendium 包以及 osgi compendium 包:
File/Import/Plug-In Development/Plug-ins and Fragments
然后选择下载包所在的目录。请参见 下面的图 1。
图 1. 导入所需的包。指定目录位置
单击 Next。在下一个对话框中,Eclipse 会显示已下载的包。请参见 下面的图 2 。
图 2. 导入所需的包,选择已下载的包
单击 Add All 和 Finish。Eclipse 会自动创建两个 Plug-In Development 项目,叫作 org.osgi.compendium
和 cxf-dosgi-ri-singlebundle-distribution
。接下来我们需要把 osgi compendium 包作为所需的包指定到 dosgi 包中。双击 cxf-dosgi-ri-singlebundle-distribution
项目中的 META-INF/MANIFEST.MF
文件。当 Eclipse 在设计模式中打开清单文件时,选择 Dependencies 选项卡,然后添加 org.osgi.compendium
作为 “Required Plug-ins”。现在您的 Eclipse 环境应该如 图 3 所示。
图 3. 导入所需的包
OSGi 容器现在已经为一些分布式服务部署做好了准备。
开发一个服务包
接下来,我们将使用一个方法创建一个基于 POJO 的简单 Web 服务,叫作 DictionaryService。这个方法就是 lookupWord(string)
,它能返回一个字符串(单词的含义)作为响应。
要在 Eclipse 中创建一个服务包,首先要确保 Perspective 被设置为 “Plug-in Development”。创建一个叫作 DictionaryService 的新 Plug-in 项目。在创建项目时,选择 com.demo.cxfdemo.Activator
作为包结构。您可以在附带包(cxf-dosgi-dw-article.zip 文件中的 DictionaryService_1.0.0.200908011529.jar)(请参见下面的 下载 链接)中找到 Activator.java, DictionaryService.java and DictionaryServiceImpl.java
,使用它们替换由 Eclipse 创建的默认的 Activator.java
。双击 DictionaryService 项目中的 META-INF/MANIFEST.MF
。Eclipse 应该会显示清单文件的设计视图。单击 Dependencies 选项卡,清除 Required Plug-ins,然后在 Imported Packages 中添加 org.osgi.framework
。您的 Eclipse 会如下面的 图 4 所示。
图 4. 创建一个服务包
Activator.java, DictionaryService.java and DictionaryServiceImpl.java
的源代码如 清单 1所示。
清单 1. DictionaryService 包代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
|
我们的 Web 服务基本上就是一个 pojo(接口和实现)。Activator 类设置服务属性并注册服务。特别值得一提的是,DictionaryService 不必实现或扩展任何 cxf 类。我们甚至不必把 dosgi 单包设置为一个必需的插件。通过应用 cxf-dosgi,在执行 Run 配置时,它将被作为一个 cxf Web 服务进行部署。
部署服务包
下一步是部署和运行服务包。为此,我们需要创建一个 Run Configuration。右键单击 DictionaryService项目,然后选择 Run As/Run Configurations
。在名为 demo_dosgi 的 OSGi Framework 文件夹中创建一个新的配置。您的 Run Configuration 弹出对话框应该如 图 5 所示。
图 5. Run 配置
单击 Apply 和 Run。现在 Eclipse 会启动它内部的 OSGi 框架(Equinox),安装和启动工作空间的三个包。您的 Eclipse 环境现在应该如 图 6 所示。
图 6. 运行包
注意,Eclipse 不会自动显示 osgi> 提示。单击一下 Console 窗口会得到此提示。在这个提示中运行命令 ss(短暂状态),查看包的状态。要获得其他可用命令清单,在提示中运行 ?。上面的显示也可以确认服务端点 URL http://localhost:9000/DictionaryService
是否可用。还可以通过在浏览器中运行 URL http://localhost:9000/DictionaryService?wsdl
来确认这一点,现在这个浏览器应该显示 WSDL 内容。把这个 xml 文档作为 DictionaryService.wsdl
保存到一个临时文件夹中。在下一小节,我们将使用它生成一个客户机。
开发 Web 客户机以调用服务
要调用新部署的 Web 服务,现在让我们创建一个简单的 Web 应用程序客户机。在 Eclipse 中切换到 Java EE Perspective,创建一个叫作 DictionaryServiceClient
的新的 Dynamic Web Application 项目。把 DictionaryService.wsdl
复制到 WebContent 文件夹中。右键单击 DictionaryService.wsdl 文件,然后选择 Web Services/Generate Client
。现在 Eclipse 应该已经在包名为 com.demo.cxfdosgi
的 src 文件夹中创建了一组客户机 Java 文件。现在我们创建一个 jsp 文件 dictionaryServiceClient.jsp
,用来调用这个服务代理,如下面的 清单 2 所示:
清单 2. dictionaryServiceClient.jsp 代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
右键单击 DictionaryServiceClient 项目,然后导出一个 war 文件 DictionaryServiceClient.war
。把这个文件复制到 C:/jakarta-tomcat-5.5.9/webapps
文件夹中。运行 C:/jakarta-tomcat-5.5.9/bin/startup.exe
,然后访问 http://localhost:8082/DictionaryServiceClient/dictionaryServiceClient.jsp
。浏览器将显示:
1 |
|
由于 Eclipse 和 Tomcat 在两个不同的 JVM 中运行,我们已经用一个分布式客户机测试了服务包。注意:把 Tomcat 的 HTTP 端口设置为 8082,这是因为 Eclipse 已经在使用 8080 部署 cxf Web 服务。
新版的服务包
把 Web 服务作为一个 OSGi 包进行部署的一个有趣功能就是可以同时部署一个 Web 服务的多个版本。现在让我们开发 DictionaryService 的下一个版本:DictionaryServiceV2。DictionaryServiceV2 的 lookupWord 方法能够返回两个字符串数组,一个表示单词的释义,另一个包含该词的同义词。由于我们修改了方法签名,显然已经破坏了现有客户机。通过把修改后的 Web 服务作为一个独立的包进行部署,我们使旧客户机能够继续运行,同时使新客户机能够使用服务的新版本。
在 Eclipse 中切换到 Plug-in Development Perspective,使用三个文件创建一个叫作 DictionaryServiceV2
的新的 Plug-in 项目。这三个文件分别是 Activator.java、DictionaryServiceV2.java 和 DictionaryServiceV2Impl.java
,源代码如下所示:
清单 3. DictionaryServiceV2 包代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
|
您的 Eclipse 窗口应该如 图 7 所示。
图 7. 创建 DictionaryServiceV2 包
编辑 demo_dosgi Run 配置,确保配置中包含了 DictionaryServiceV2
包,如 图 8 所示。
图 8. 修改后的 Run 配置
单击 Apply 和 Run。现在 Eclipse 会重新启动 OSGi 框架,安装第四个包(DictionaryServiceV2
),然后启动所有的四个包。现在您的 Eclipse 会如 图 9 所示。
图 9. 运行包
这将确认所有的四个包都已安装并且正在运行。日志消息也可以确定服务端点:
http://localhost:9000/DictionaryService
和
http://localhost:9000/DictionaryServiceV2
处于激活状态。在浏览器中访问第二个服务,如 http://localhost:9000/DictionaryServiceV2?wsdl
,然后把显示的 wsdl 内容保存到文件 DictionaryServiceV2.wsdl
中。
调用新服务
要调用新版本的 Web 服务,我们需要生成一个新的客户机。创建一个新的项目 DictionaryServiceV2Client
作为一个 Dynamic web Application。使用与第一个版本相同的步骤复制 wsdl 并生成 Java 客户机。创建一个新的 jsp 文件 dictionaryServiceV2Client.jsp
,如:
清单 4. dictionaryServiceV2Client.jsp 代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
把这个项目作为 DictionaryServiceV2Client.war 导出,然后把它安装到运行在 Eclipse 外部的 tomcat 服务器中。现在在浏览器中访问 http://localhost:8082/DictionaryServiceV2Client/dictionaryServiceV2Client.jsp
时应该显示为:
1 2 |
|
现在我们已经成功地开发、部署和测试了一个 Web 服务的两个版本。
结束语
在本文中,我没有使用 pojo 服务包中的任何 cxf-dosgi API 类。然而,可以通过编辑 manifest.mf 文件(前面的 “导入包” 部分),导入指定包来使用 cxf-dosgi 类。注意,所有 J2SE 类本质上说都可用于一个包。但是,要从一个服务包中使用任何 JEE 服务(如发送邮件等),您需要通过编辑 manifest.mf 来导入具体的 JEE 包。Eclipse 提供了大部分可导入的 JEE 包。
我已经描述了把 Web 服务作为一个 OSGi 包进行开发和部署以及使用一个简单的 web 应用程序客户机调用服务的详细方法。我还讨论了 SOA 策略对于在一个整洁的 OSGi 容器环境中同时部署和支持一个服务的多个版本的好处。
下载资源
- 用于本文的 Service 和 Client 包 (cxf-dosgi-dw-article.zip | 3,562KB)
相关主题
- 在 OSGi Alliance 中了解更多有关 OSGi 规范的内容。
- 查看一些受欢迎的 OSGi 容器 “Eclipse Equinox” 和 “Apache Felix”。
- “Web 服务版本控制最佳实践”(developerWorks,2004 年 1 月):在本文中,Kyle Brown 和 Michael Ellis 将概述 Web 服务开发人员所面对的版本控制困难的范围,并且提供一些解决方案模板,讨论解决这个问题的体系结构和最佳实践。。
- “Designing and versioning compatible Web services”,面向 Web 服务版本控制的策略。
- “Eclipse IDE for Java EE Developers”,下载 Eclipse 3.5(包括 Equinox),用于开发和部署 OSGi 包。
- “Apache cxf-dosgi”,下载 Apache cxf-dosgi 单包发行版(jar)。
- “OSGi Compendium 包”,用于 cxf-dosgi 的包。
- “Apache Tomcat 5.5.9”,用来部署调用 OSGi 服务包的 web 客户机的 Servlet 容器。
- 下载 IBM 产品评估版 或 在线试用 IBM SOA Sandbox,并开始使用来自 DB2®、Lotus®、Rational®、Tivoli® 和 WebSphere® 的应用程序开发工具和中间件产品。
- developerWorks SOA and Web services 专区:让您了解更多和 SOA 以及 Web 服务相关的内容,包括技术文章、教程以及特殊专题等。
from: https://www.ibm.com/developerworks/cn/webservices/ws-OSGi/index.html