您的位置:首页 > 运维架构 > Apache

OSGI--apache felix 入门

2012-03-30 17:05 274 查看
引言

本文是本系列的第 1 部分,我们将开发包含客户端和服务器端组件的订单应用程序。然后将这些组件打包为 OSGi 包。客户端调用服务组件处理订单。服务组件具有处理订单和打印订单 ID 的方法。阅读本文后,您可以应用 Apache Felix 的概念和功能来将 Java 组件类构建和打包为 OSGi 包。

系统要求

要运行本文中的示例,请确保已在计算机上安装和设置了以下软件:

Java 5 或更高版本

Ant 构建工具

Apache Felix 二进制分发版 1.0.4

接下来,设置以下环境变量(按照示例 ANT_HOME=C:\apache-ant-1.7.0 进行设置):

JAVA_HOME(用于 Java)

ANT_HOME(用于 Ant)

接下来,将以下内容添加到 PATH 环境变量:

JAVA_HOME\bin

ANT_HOME\bin

回页首

OSGi

OSGi 规范以更为动态的方式定义和传播 Java 应用程序的模块化。通常,Java 应用程序模块化为 JAR 包。但是使用 JAR 文件有局限性:

JAR 包通过类路径环境变量解析,而这并未提供管理 JAR 依赖关系的可靠框架。

JAR 无法进行版本控制,因此无法跟踪所创建或修改的 JAR 包的历史。

没有用于在运行时出现代码更改的情况下动态更新 JAR 文件的框架。

为了处理上述问题,可以使用 OSGi 框架,因为其中对 Java 的模块化系统进行了重新定义。相对于传统的 JAR 模块而言,基于 OSGi 的系统具有以下优势:

OSGi 提供了可靠的集成环境,包可以在其中作为服务发布并导出供其他包使用。

OSGi 为每个新组件提供了包版本控制功能。因此可以跟踪包创建和更改的历史。

通过 OSGi,可以在运行时出现更改的情况下随时动态更新包。

目前有三个已知的 OSGi 实现:

Equinox

Knopflerfish

Felix

本系列文章将介绍如何将 Felix 作为 OSGi 容器使用。本系列文章涵盖以下主题:

第 1 部分介绍如何使用 OSGi API 进行组件开发。

第 2 部分将重点介绍在 OSGi 容器中使用 Spring 和从组件类消除 OSGi API 依赖关系,从而使其成为传统 Java 对象(plain old Java objects,POJO)。这样做的优势在于,只需将重点放在编写组件类中的业务方法上,而由 Spring 配置文件处理组件的生命周期。

回页首

订单应用程序

接下来让我们看看如何使用基于 Felix 的 OSGi 框架创建订单应用程序包。此应用程序包括两个组件:OrderClient.java(客户端)和 OrderService.java(服务器端)。客户端组件打包为 client.jar,服务器组件打包为 order.jar。接下来让我们首先看看
OrderClient
类。

清单 1. 客户端组件 OrderClient

public class OrderClient implements BundleActivator {

private ServiceTracker orderTracker;
private OrderService orderService;

public void setService(OrderService orderService) {
this.orderService = orderService;
}

public void removeService() {
this.orderService = null;
}

public void start(BundleContext context) throws Exception {
orderTracker =
new ServiceTracker(context, OrderService.class.getName(), null);
orderTracker.open();
OrderService order = (OrderService) orderTracker.getService();

if (order == null) {
System.out.println("Order service not available");
} else {
order.processOrder();
}
}

public void stop(BundleContext context) {
System.out.println("Bundle stopped");
orderTracker.close();
}

}

正如清单 1 中所示,
OrderClient
OrderService
组件调用
processOrder
方法,以在启动 client.jar 包时打印
orderID
。此类实现
BundleActivator
接口,该接口具有两个回调方法:
start()
stop()
。启动和停止客户端包时,Felix
容器将调用实现的
start()
stop()
方法。

接下来让我们仔细分析一下
start()
方法。在
start()
方法中,首先获得
ServiceTracker
类的引用。您可以将此类视为工厂类。然后通过调用此
getService
方法从此工厂类获取服务引用。
ServiceTracker
使用以下参数构造:包上下文和
OrderService
类的名称。

清单 2. OrderService 实现

public class OrderServiceImpl implements OrderService, BundleActivator {

private ServiceRegistration registration;

public void start(BundleContext context) {
registration =
context.registerService(OrderService.class.getName(), this, null);
System.out.println("Order Service registered");
}

public void stop(BundleContext context) {
System.out.println("Order Service stopped");
}

public void processOrder() {
System.out.println("Order id: ORD123") ;
}
}

服务器端 order.jar 文件包含两个组件:
OrderService
接口和
OrderServiceImpl
类。此接口具有由
OrderServiceImpl
类实现的抽象类
processOrder
。此类还实现了
BundleActivator
接口,此接口供
Felix 容器调用来启动和停止 order.jar 包。
start()
方法在注册中心注册
OrderService
组件,以供客户端包使用。注册与导出对象供其他包使用的作用一样。

回页首

通过 Manifest 通信

真正的问题是,客户端包如何知道注册的服务包?此通信通过使用 Manifest 文件处理。在 Manifest 文件中,在导入和导出程序包中提供包的引用。客户端包 Manifest 通常导入服务组件程序包,而服务包 Manifest 导出自己的程序包。请注意,当包 A 导入包 B 的程序包时,包 B 必须导出自己的程序包。没有恰当的导入和导出定义,通信将失败。

清单 3. 客户端清单文件

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Order Service Client
Bundle-SymbolicName: orderclient
Bundle-Version: 1.0.0
Bundle-Activator: order.client.OrderClient
Import-Package: org.osgi.framework, org.osgi.util.tracker, order

清单 4. 服务器清单文件

Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Order Service
Bundle-SymbolicName: orderservice
Bundle-Version: 1.0.0
Export-Package: order
Bundle-Activator: order.impl.OrderServiceImpl
Import-Package: org.osgi.framework

对于订单应用程序,client.jar 包 Manifest 中包含条目
Import-Package: org.osgi.framework, org.osgi.util.tracker, order
。这个实际上表示,客户端包导入核心 OSGi 程序包和
OrderService
程序包。类似地,order.jar 包清单包含条目
Export-Package:
order
。即,包导出其程序包供客户端使用。如果导入和导出未显式声明,OSGi 将引发运行时错误。

Manifest 文件还包含其他信息,如包激活器类的名称等。激活器类负责在包中调用
start()
stop()
方法。在本例中,client.jar 包的激活器类为
OrderClient
,order.jar 包的激活器类为
OrderService


回页首

部署

在部署和使用包前,请进行以下工作:

根目录 C:\osgi 文件夹下创建图 1 中所示的目录结果,并将本文前面介绍的组件放入其中:

Java 代码放入相应的程序包文件夹(客户端和服务)。

清单文件放入相应的 META-INF 文件夹(客户端和服务)。

图 1. 代码目录结构



下一步便是部署这些包。请通过以下步骤,使用 Felix OSGi 容器部署客户端和服务包:

在服务文件夹中使用 ANT 运行 build.xml。

在客户端文件夹中使用 ANT 运行 build.xml。

执行了上述构建文件后,将分别在 client/bin 和 service/bin 文件夹中创建 client.jar 和 order.jar 包。

在 Microsoft® Windows® 命令提示符中运行 startfelix.bat,以启动 Felix 运行时。

每次启动 Felix 运行时,都会提示配置文件名称。配置文件名称的作用类似于项目名称。可以提供任何名称作为项目配置文件的名称。对于 Felix 运行时的每次后续启动,如果提供了之前输入的相同配置文件名称,Felix 将会加载与该项目名称关联的所有已安装包。如果提供了新配置名称,则将需要再次显式安装各个包:

在 Felix Shell 中提供以下命令,以安装各个包:

install file:service/bin/order.jar


install file: client/bin/client.jar


start service_bundle_id


start client_bundle_id


为了指示包的 ID,可以使用
ps
命令。必须首先启动服务包,然后启动客户端包。在启动相应的包时,将显示以下输出(请参见图 2)。

图 2. 程序输出



还可以通过在 Felix Shell 提供
update bundle_id
命令更新包。包将在运行时动态更新。

回页首

结束语

本文简单介绍了 OSGi 框架的功能和概念,并说明了如何使用其创建动态 JAR 包。您了解了如何构建并将组件打包为 OSGi 包,然后在 Felix 运行时环境中运行。我们还了解了如何创建包 Manifest 文件,以作为包之间的通信接口使用。

OSGi 提供了一种新的构建和管理 JAR 包的方式。请继续关注本系列的第 2 部分,我们将介绍 Spring 框架在 OSGi 环境中如何代替 OSGi 承担管理包的责任。

资源使用说明:

下连接的资源中,felix版本为 1.4.0,所需要的环境文中已经说明。需要注意的是:

在运行ant编译service以及client时,修改client/build.xml 中的felix_home 变量,否则会出现编译出错。

使用到的下载地址:

http://download.csdn.net/detail/icecream0/4187317
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: