OSGi原理与最佳实践:第二章 基于Spring-DM实现Petstore(1)

 由  ValRay 发布

第 2 章 基于Spring-DM实现Petstore

在前面一章,我们分别介绍了 Equinox、Felix 和 Spring Dynamic Modules,并完成了简单的 HelloWorld 程序。接下来将通过 Spring Dynamic Modules 完成一个简化的 PetStore 例子。

2.1 “即插即用”的Petstore

2.1.1 Petstore的功能需求

Petstore 是 J2EE 的 BluePrints 中提到的一个例子,里面涉及了很多 J2EE 的规范及使用,新的 Petstore 实现中也引入了 Ajax 的技术。也有其他的语言实现了 Petstore 并和 J2EE 的实现进行比较。在本章中,我们并不想去完整地做一个 Petstore 的实现,而是想去实现一个从功能上说简化版的 Petstore。而我们的重点是希望给大家展现一个全新的“即插即用”的 Petstore。

首先来看这次要实现的 Petstore 包含的功能。

>类目产品展示

列出所有的类目,并且配有类目的图片。

列出类目下所有产品的名称。

在页面上提供点击某个产品后进入到产品详细信息页面的功能。

产品详细信息中列出产品所属的类目、产品名称和属于该产品的具体条目。

 每个条目后可以选择将该条目放入到购物车中。

 提供返回到类目列表的按钮。

>购物车

 显示目前购物车中的条目列表。

 每个条目显示类目图片,条目的 ID、名称、描述、单价、数量和小计。

显示总计的价格。

提供回到类目列表继续购物的按钮。

能够删除购物车中的某个条目。

能够修改购物车中的某个条目的数量。

>库存管理

 列出类目。

 列出类目中包含的产品。

点击产品进入到产品的详细信息页面。

 列出产品包含的具体条目的列表。

显示产品中每个条目的 ID、单价、描述、库存数量等信息。

管理和权限的管理及支付的功能,这几个部分可以作为课后的作业,给广大读者在已有的 Petstore 的基础上去扩展完成。

所谓“即插即用”的 Petstore,就是要我们实现的 Petstore 中的功能模块能够动态地加载和卸载。也就是希望模块加载了,这个功能就可用,而模块卸载了,这个功能就停用。这就要求功能是模块化的,并且是可动态插拔的模块化而不仅仅是静态设计上的模块化。

2.1.2 OSGi框架的功能和设计思想

下面,我们先来看 OSGi 框架能提供的基础功能。

1.支持模块化的动态部署

基于 OSGi 而构建的系统可以以模块化的方式(例如 jar 文件等)动态地部署至框架中,从而增 加、扩展或改变系统的功能。

要以模块化的方式部署到 OSGi 中,必须遵循 OSGi 的规范要求,那就是将工程创建为符合规范 的 Bundle 工程(就是 Eclipse 中的插件工程),或者使用工具将工程打包成符合规范的 Jar 文件。

2.支持模块化的封装和交互

OSGi 支持模块化的部署,因此可以将系统按照模块或其他方式划分为不同的 Java 工程,这和以往做 Java 系统时逻辑上的模块化是有很大不同的,这样做就使得模块从物理级别上隔离了,也就不可能从这个模块直接调用另外模块的接口或类了。根据 OSGi 规范,每个工程可通过声明 Export-Package 对外提供访问此工程中的类和接口,也可通过将要对外提供的功能声明为 OSGi 的服务实现面向接口、面向服务式的设计。

基于 OSGi 的 Event 服务也是实现模块交互的一种可选方法,模块对外发布事件,订阅了此事件的模块就会相应地接收到消息,从而做出处理。

3.支持模块的动态配置

OSGi 通过提供 Configuration Admin 服务来实现模块的动态配置和统一管理,基于此服务各模块的配置可在运行期间进行增加、修改和删除,所有对于模块配置的管理统一调用 Configuration Admin 服务接口来实现。

4.支持模块的动态扩展

基于 OSGi 提供的面向服务的组件模型的设计方法,以及 OSGi 实现框架提供的扩展点方法可实现模块的动态扩展。

那么,要使用 OSGi 框架提供的这些基本功能,在设计系统时就要遵循 OSGi 框架的设计思想:

5.模块化的设计

模块化的设计已经是大家在做系统设计时遵循的基本设计原则,但只有基于 OSGi 来做模块化的时候才会真正体验到何谓模块化,因为 OSGi 中的模块化是物理隔离的,而不基于 OSGi 的话很难做到物理隔离方式的模块化实现,也就很难使系统真正做到模块化,通常切换到基于 OSGi 后就会发现以前的模块化设计做得还是很不足。

基于 OSGi 进行模块化设计和传统的模块设计并没有多大的差别,均为定义模块的范围、模块对外提供的服务和所依赖的服务,相信大家在这点上很容易适应,在 OSGi 中只是更为规范,更为遵循面向服务的设计思想。

在 OSGi 中模块由一个或多个 Bundle 构成,模块之间的交互通过 Import-Package、Export-Package 及 OSGi Service 的方式实现。

6.面向服务的组件模型的设计

面向服务的组件模型(Service-Oriented Component Model)的设计思想是 OSGi 的核心设计思想,OSGi 推崇系统采用 Bundle 的方式来划分,Bundle 由多个 Component(组件)来实现,Component 通过对外提供服务接口和引用其他 Bundle 的服务接口来实现 Component 间的交互。

这个核心的设计思想上可以看出,基于 OSGi 实现的系统自然就是符合 SOA 体系架构的。

在 OSGi 中 Component 以 POJO 的方式编写,通过 DI 的方式注入其所引用的服务,以一个标准格式的 XML 描述 Component 引用服务的方式、对外提供的服务及服务的属性。

7.动态化的设计

动态化的设计是指系统中所有的模块均须支持动态的插拔和修改,系统的模块要遵循对具体实现的零依赖和配置的统一维护(基于 Configuration Admin 服务),在设计时要记住的是所依赖的 OSGi 服务或 Bundle 都是有可能动态卸载或安装的。对于模块的动态插拔和修改,OSGi 框架本身提供了支持,模块可通过 OSGi 的 Console(命令行 Console、Web console 等)安装、更新、卸载、启动、停止相应的 Bundle。

为保持系统的动态性,在设计时要遵循的原则是不要静态化地依赖任何服务,避免服务不可用时 造成系统的崩溃,从而保证系统的“即插即用,即删即无”。

8.可扩展的设计

OSGi 在设计时提倡采用可扩展式的设计,即可通过系统中预设的扩展点来扩充系统的功能,有两种方式来实现。

引用服务的方式,通过在组件中允许引用服务接口的多个实现来实现组件功能的不断扩展,例如 A 组件的作用为显示菜单,它通过引用菜单服务接口来获取系统中所有的菜单服务,此时系统中有两个实现此服务的组件,分别为文件菜单组件和编辑菜单组件,那么 A 组件相应地就会显示出文件菜单和编辑菜单,而当从系统中删除编辑菜单的组件时,A 组件显示的菜单就只剩文件菜单了,若此时再部署一个实现菜单服务接口的视图菜单组件模块到系统中,那么显示出来的菜单则会为文件、视图。

定义扩展点的方式,按照 Eclipse 推荐的扩展点插件的标准格式定义 Bundle 中的扩展点,其他要扩展的 Bundle 可通过实现相应的扩展点来扩展该 Bundle 的功能。 系统对于可扩展性的需求很大程度会影响到 Bundle 的划分和设计,这要结合实际情况来进行设计。
查看评论