HelloWorld
一般情况下,学习一门新的技术,程序员都习惯于首先开发一个 hello world 应用程序,这似乎也是一种“工业标准”。好的,让我们开始吧,开发一个简单的 OSGi 应用程序并不难,步骤如下:
- 建立一个 plug-in 工程,File > New > Project,选择 Plug-in development > Plug-in Project
图 1. 新建 plug-in 工程
- 在建立工程的第一个向导,填入工程的名称:
osgi.test.helloworld
,使用缺省的工程路径。注意目标平台的选择,由于我们的项目是一个通用的 OSGi bundle,所以选择 equinox 。
图 2. 填入工程名及选择目标平台
- 在下一个向导界面中,填入需要的一些插件信息(注意 Eclipse 中的插件概念基本类似于 OSGi 中的 bundle 的概念),这里需要填入的是 OSGi 的 provider(供应商)和 classpath 。如果没有特别的设计,一般可以忽略这两个字段 。最后是关于 activator 的部分,如果不是一个 fragment bundle 则需要填入,除非您的 bundle 自己实现框架的事件监听,这个似乎也没有必要。因此,建议使用缺省的设置,如图 3:
图 3. 使用缺省设置Activator:这是 bundle 启动时首先调用的程序入口,相当于 Java 模块中的 main 函数。不同的是,main 需要通过命令行调用,而 OSGi 的 Activator 是被动的接受 OSGi 框架的调用,收到消息后才开始启动。
最佳实践:不要在 Activator 中写太多的启动代码,否则会影响 bundle 启动速度,相关的服务启动可以放到服务的监听器中。
- 最后一步,不使用任何的模板,所以勾掉缺省的选项,点击完成,如图 4:
图 4. 勾掉缺省的选项
- 完成,基本的插件视图如图 5,Eclipse 会在工程名下建立相同路径的 Java Package,其中包含了 Activator 类,插件的配置信息也都放在 MANIFEST.MF 文件中,将来我们相当多的工作都是在其中完成。
图 5. 基本的插件视图
- 编辑 Activator.java,输入 hello world 语句,代码如下:
清单 1. 编辑 Activator.java
package osgi.test.helloworld;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
public class Activator implements BundleActivator {
/*
* (non-Javadoc)
* @see org.osgi.framework.BundleActivator
* #start(org.osgi.framework.BundleContext)
*/
public void start(BundleContext context) throws Exception {
System.out.println("hello world");
}
/*
* (non-Javadoc)
* @see org.osgi.framework.BundleActivator
* #stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext context) throws Exception {
}
}我们可以看到每个 Activator 实际都是实现了
BundleActivator
接口,此接口使 Activator 能够接受框架的调用。在框架启动后,启动每个 bundle 的时候都会调用每个 bundle 的 Activator 。注意:bundle 的 Activator 必须含有无参数构造函数,这样框架才能使用
Class.newInstance()
方式反射构造 bundle 的 Activator 实例。这里我们在
start
方法中填入了我们希望输出的 hello world 字符串。那么,怎么才能启动这个 bundle 呢? - 执行:选择 Run > Open Run Dialog,进入运行菜单,在 OSGi framework 中右键点击选择 new 一个新的 OSGi 运行环境,如图:
图 6. 新建 OSGi 运行环境在右边的运行环境对话框中,输入运行环境的名字、start level 和依赖的插件,由于我们目前不需要其它的第三方插件,因此只需要勾上系统的 org.eclipse.osgi 插件,如果不选择此插件,hello world 将无法运行。如图 7,只有当您点击了 validate bundles 按钮 ,并且提示无问题之后,才表明您的运行环境基本 OK 了。
图 7. 选择 org.eclipse.osgi插件依赖插件的选择:
图 8. 依赖插件的选择好的,如果您的运行环境已经 OK,那么就点击 Run 吧。
图 9. 运行 OSGi 项目恭喜您,成功了!
-
OSGi 控制台
OSGi 控制台对于习惯开发普通 Java 应用程序的开发人员来说,还是比较新鲜的。一般来说,通过 OSGi 控制台,您可以对系统中所有的 bundle 进行生命周期的管理,另外也可以查看系统环境,启动、停止整个框架,设置启动级别等等操作。如图 10,键入
SS
就可以查看所有 bundle 的状态:
图 10. 查看所有 bundle 的状态
下面列出了主要的控制台命令:
表 1. Equinox OSGi 主要的控制台命令表类别 命令 含义 控制框架 launch
启动框架 shutdown
停止框架 close
关闭、退出框架 exit
立即退出,相当于 System.exit init
卸载所有 bundle(前提是已经 shutdown) setprop
设置属性,在运行时进行 控制 bundle Install
安装 uninstall
卸载 Start
启动 Stop
停止 Refresh
刷新 Update
更新 展示状态 Status
展示安装的 bundle 和注册的服务 Ss
展示所有 bundle 的简单状态 Services
展示注册服务的详细信息 Packages
展示导入、导出包的状态 Bundles
展示所有已经安装的 bundles 的状态 Headers
展示 bundles 的头信息,即 MANIFEST.MF 中的内容 Log
展示 LOG 入口信息 其它 Exec
在另外一个进程中执行一个命令(阻塞状态) Fork
和 EXEC 不同的是不会引起阻塞 Gc
促使垃圾回收 Getprop
得到属性,或者某个属性 控制启动级别 Sl
得到某个 bundle 或者整个框架的 start level 信息 Setfwsl
设置框架的 start level Setbsl
设置 bundle 的 start level setibsl
设置初始化 bundle 的 start level MANIFEST.MF
MANIFEST.MF 可能出现在任何包括主类信息的 Jar 包中,一般位于 META-INF 目录中,所以此文件并不是一个 OSGi 特有的东西,而仅仅是增加了一些属性,这样也正好保持了 OSGi 环境和普通 Java 环境的一致性,便于在老的系统中部署。表 2 列出此文件中的重要属性及其含义:
表 2. MANIFEST.MF 文件属性属性名字 含义 Bundle-Activator
Bundle 的启动器 Bundle-SymbolicName
名称,一般使用类似于 JAVA 包路径的名字命名 Bundle-Version
版本,注意不同版本的同名 bundle 可以同时上线部署 Export-Package
导出的 package 声明,其它的 bundle 可以直接引用 Import-Package
导入的 package Eclipse-LazyStart
是否只有当被引用了才启动 Require-Bundle
全依赖的 bundle,不推荐 Bundle-ClassPath
本 bundle 的 class path,可以包含其它一些资源路径 Bundle-RequiredExecutionEnvironment
本 bundle 必须的执行环境,例如 jdk 版本声明