OSGi 开发手册

王勇

贡献于2013-07-02

字数:16396 关键词: OSGi 手册

目录 一、OSGI介绍 2 1.1 历史背景 2 1.2 OSGi框架介绍 2 1.3 OSGi结构图 2 二、开发环境部署 4 2.1 开发工具和环境 4 2.2 配置插件工程所依赖的包 4 三、开发入门 4 3.1 创建数据源bundle 4 3.2 创建测试bundle 8 四、应用的部署与启动 13 4.1 部署与启动 13 4.2 常用命令 17 五、常见问题 18 5.1 如何发布和引用远程服务 18 5.1.1 标准配置 18 5.1.2 自定义配置 19 5.2 OSGi manifest.mf 选项简介 23 一、OSGI介绍 1.1 历史背景 什么是OSGi 呢?OSGi(Open Service Gateway Initiative)字面上的意思是一个公共的服务平台。1999年OSGi 联盟成立,它是一个非盈利的国际组织,旨在建立一个开放的服务规范,为通过网络向设备提供服务建立开放的标准,是开放业务网关的发起者。OSGi 联盟的初始目标是构建一个在广域网和局域网或设备上展开业务的基础平台。历史总是具有惊人的相似性,正如Java 诞生于一个嵌入式开发的项目中,却被应用于网络平台的开发,对OSGi 的最早设计也是针对嵌入式应用的,诸如机顶盒、服务网关、手机、汽车等都是其应用的主要环境。后来,由于OSGi 的诸多优秀特性(可动态改变系统行为,热插拔的插件体系结构,高可复用性,高效性等等),它被应用于许多PC 上的应用开发,因此逐步为开发者所知和钟爱。 1.2 OSGi框架介绍 1. Equinox Equinox是Eclipse开源组织关于OSGi R4版本规范核心框架的实现 2. Felix Felix是Apache关于OSGi R4版本规范的实现。 3. Spring-DM Spring-DM 指的是 Spring Dynamic Modules。Spring-DM 的主要目的是能够方便地将Spring 框架和OSGi框架结合在一起,使得使用Spring的应用程序可以方便简单地部署在OSGi环境中, 利用OSGi框架提供的服务,将应用变得更加模块化。 4. Apache CXF Apache CXF是一个开源的Service框架,它实现了JCP与Web Service中一些重要标准。CXF简化了构造,集成,面向服务架构(SOA)业务组件与技术的灵活复用。在CXF中,Service使用WSDL标准定义并能够使用各种不同的消息格式(或binding)和网络协议(transports)包括SOAP、XML(通过HTTP或JMS)进行访问。CXF同样支持多种model 如:JAX-WS,JBI,SCA和CORBA service。CXF设计成可灵活部署到各种容器中包括Spring-based,JBI,SCA, Servlet和J2EE容器。 Apache CXF 通过Web Service的方式实现了分布式OSGi的请求调用,并且是通过WSDL对外暴漏了Web Service。(具体使用参照5.1节) 1.3 OSGi结构图 解释一下上图中每一层的含义,其中OS 层和JVM 层可以不用详细介绍了,重点需要关注的是应用程序Bundles 层。框架本身提供的类加载,生命周期管理,服务注册和规范服务也都是针对Bundles 的。每一个在OSGi 框架中运行的逻辑单元称为一个Bundle,Bundle 实际是一个符合特定形式的jar 文件。每一个Bundle 的功能可以是抽象的也可以是具体的。所谓抽象,就是它不是一个具体的应用,没有完成一些业务功能,而只暴露了一些接口或者功能给其他的Bundle 使用;所谓具体,就是该Bundle 可以独立的完成一个功能,例如连接数据库,获取数据等等。Bundle 有六种状态,分别是:installed(安装完成,本地资源成功加载),resolved(依赖关系满足,即该Bundle 要么是准备好运行了,要么是已经被停止了),starting(Bundle 正在被启动),stopping(Bundle 正在被停止),active(Bundle 被激活,正在运行中),uninstalled(Bundle 被卸载了)。OSGi 有它自身的类加载机制从而控制这些加载的Bundles 彼此之间的依赖关系,而生命周期管理也是OSGi 的一大亮点,由于可动态的对这些加载的Bundles 进行安装、卸载、启动、停止等操作,所以可以动态的改变应用程序的运行状态。当一系列的Bundles 存在于服务器中的时候,那么它们之间必然会存在通信协作的部分,比如说一个通过网页捕获用户输入的Bundle 执行的时候,它必须首先需要一个Web 服务器服务的支持,那么这个时候服务注册器就会从整个OSGi容器中寻找这个服务,如果能完成服务的匹配,那么相应的功能就会很自然的实现了。OSGi 规范还规定了一组预设的服务,包括日志、服务管理等等,这些服务在主流的开源框架中都有实现。OSGi 框架中还包括一个安全层,OSGi 的安全层扩展了Java 的安全机制,增并加了一些新的约束以填补了Java安全机制中的遗漏。 二、开发环境部署 2 2.1 开发工具和环境 jdk1.6+eclipse3.5 2.2 spring –MD 和 CXF-DOSG作用及下载地 1> spring-MD 是指Spring Dynamic Modules,主要目的就是能够方便的将spring 框架 osgi 框架结合在一起,使得应用程序可以方便的部署osgi 环境中,利用osgi 框架提供服务,将应用变得模块化, 下载最新版本1.2.1RCl,地址http://www.springsource.org/download/community?project=Spring%20Dunamic%20Modules & version=1.2.0 2> CXF-DOSG 主要是通过web service 的方式实现分布式osgi的请求和调用,并且通过wsdl 对外暴露web service。 下载最新版本 1.1. ,地址 http://www.apache.org/dist/cxf/dosgi/1.1/cxf-dosgi-ri-multibundle-distribution-1.1.zip 2.3配置插件工程所依赖的包 Perferences->Plug-in Development->Target PlatForm->add 依赖jar包:(包含spring-DM,cxf所需的jar包) 三、开发入门 利用spring-DM实现数据源的共用 3 3.1 创建数据源bundle 1、创建maven工程 点击next > 点击finish 2、将maven转为插件工程 在工程名上点击鼠标右键->configure->convert to Plug-in projects… 工程结构图如下: src/main/java包:代码编写 src/test/java包:单元测试 3、在META-INF下创建spring文件夹: 在spring文件夹下创建文件: jdbc.xml:加载数据源 services-publish-cxf.xml: 以cxf发布webservice 4、在bundle下创建lib包 用于存放bundle所依赖其他jar包 5、代码编写 jdbc.xml: services-publish-cxf.xml: 添加所需jar: commons-dbcp-1.2.2.jar commons-pool-1.3.jar oracle-jdbc-10g.jar spring-beans-2.5.6.jar spring-dao-2.5.6.jar spring-jdbc-2.5.6.jar MANIFEST.MF中导入jar: 这样数据源就发布出去了,在2.2中对数据源进行引用和测试 3.2 创建测试bundle 1、创建maven工程 点击next > 点击finish 2、将maven转为插件工程 在工程名上点击鼠标右键->config->convert to Plug-in projects… 工程结构图如下: 3、创建spring文件 在META-INF下创建spring文件夹: 在spring文件夹下创建文件: bean.xml:模块中spring的配置文件 services-publish-cxf.xml:以cxf发布webservice services-reference-cxf.xml:引用其他模块的webservice 注:每个spring配置文件在bundle用到时创建 4、在bundle下创建lib包 用于存放bundle所依赖其他jar包 工程结构图如下: 5、引用和测试2.1中发布的数据源 services-reference-cxf.xml: bean.xml: com.sntele.surfing.ability.demo.TestDataSource类: import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.jdbc.core.JdbcTemplate; public class TestDataSource { public static final Log log = LogFactory.getLog(TestDataSource.class); private JdbcTemplate jdbcTemplate; public void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public void init() throws Exception{ int count = jdbcTemplate.queryForInt("select count(*) from sms_log"); log.info("count:" + count); } } 所需jar包: spring-beans-2.5.6.jar spring-dao-2.5.6.jar spring-jdbc-2.5.6.jar MANIFEST.MF中导入上面的jar包 MANIFEST.MF添加项目依赖插件: 6、运行bundle: 打开Run->Run Configurations 在OSGi Framework菜单项上点击鼠标右键->new 如下图选择所需启动的bundle,并点击run按钮启动: 注:如果运行过程中报: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.oohla.test.TestDataSource#0' defined in URL [bundleentry://155.fwk7031149/META-INF/spring/beans.xml]: Invocation of init method failed; nested exception is org.springframework.aop.AopInvocationException: AOP configuration seems to be invalid: tried calling method [public abstract java.sql.Connection javax.sql.DataSource.getConnection() throws java.sql.SQLException] on target [com.thewebpagestudio.util.jdbc.BasicDataSource@c932df]; nested exception is java.lang.IllegalArgumentException: object is not an instance of declaring class 错误 解决方法:在jvm设置中添加-Dorg.osgi.framework.bootdelegation=* 运行结果: count:256 四、应用的部署与启动 4 4.1 部署与启动 1、 创建独立的Equinox运行环境 A.在硬盘上建一个部署目录osgi_demo,从eclipse的plugins目录中复制org.eclipse.osgi_3.5.2.R35x_v20100126.jar到osgi_demo下,并修改其名称为equinox.jar B.编写run.bat 内容:java -jar equinox.jar -console 2、 导出各个bundle为jar 点击next > 设置导出路径,并点击finish 3、 安装bundle到Equinox中 在osgi_demo下创建bundles目录,将所有依赖包拷贝到里面 两种启动方式: 第一种. 运行run.bat,先安装依赖jar 输入: install reference:file:plugins/com.springsource.org.aopalliance-1.0.0.jar 依次为例依次安装其他依赖jar 安装往后输入start 命令进行启动(用法:start+空格+id) 第二种:在osgi_demo目录下创建configuration文件夹,在configuration文件夹下创建config.ini文件,文件的内容如下: org.osgi.framework.bootdelegation=* osgi.bundles=\ reference\:file\:plugins/com.springsource.org.aopalliance-1.0.0.jar@start,\ reference\:file\:plugins/com.springsource.org.jdom-1.0.0.jar@start,\ reference\:file\:plugins/cxf-bundle-minimal-2.2.4.jar@start,\ reference\:file\:plugins/cxf-dosgi-ri-discovery-local-1.1.jar@start,\ reference\:file\:plugins/cxf-dosgi-ri-dsw-cxf-1.1.jar@start,\ reference\:file\:plugins/geronimo-activation_1.1_spec-1.0.2.jar@start,\ reference\:file\:plugins/geronimo-annotation_1.0_spec-1.1.1.jar@start,\ reference\:file\:plugins/geronimo-javamail_1.4_spec-1.2.jar@start,\ reference\:file\:plugins/geronimo-ws-metadata_2.0_spec-1.1.2.jar@start,\ reference\:file\:plugins/javax.servlet_2.5.0.v200806031605.jar@start,\ reference\:file\:plugins/org.apache.commons.logging_1.0.4.v200904062259.jar@start,\ reference\:file\:plugins/org.apache.servicemix.bundles.asm-2.2.3_1.jar@start,\ reference\:file\:plugins/org.apache.servicemix.bundles.jaxb-impl-2.1.6_1.jar@start,\ reference\:file\:plugins/org.apache.servicemix.bundles.neethi-2.0.4_1.jar@start,\ reference\:file\:plugins/org.apache.servicemix.bundles.woodstox-3.2.7_1.jar@start,\ reference\:file\:plugins/org.apache.servicemix.bundles.wsdl4j-1.6.1_1.jar@start,\ reference\:file\:plugins/org.apache.servicemix.bundles.xmlresolver-1.2_1.jar@start,\ reference\:file\:plugins/org.apache.servicemix.bundles.xmlschema-1.4.3_1.jar@start,\ reference\:file\:plugins/org.apache.servicemix.bundles.xmlsec-1.3.0_1.jar@start,\ reference\:file\:plugins/org.apache.servicemix.specs.jaxb-api-2.1-1.3.0.jar@start,\ reference\:file\:plugins/org.apache.servicemix.specs.jaxws-api-2.1-1.3.0.jar@start,\ reference\:file\:plugins/org.apache.servicemix.specs.saaj-api-1.3-1.3.0.jar@start,\ reference\:file\:plugins/org.apache.servicemix.specs.stax-api-1.0-1.3.0.jar@start,\ reference\:file\:plugins/org.eclipse.osgi.services_3.2.0.v20090520-1800.jar@start,\ reference\:file\:plugins/pax-web-service-0.5.1.jar@start,\ reference\:file\:plugins/spring-aop-2.5.6.jar@start,\ reference\:file\:plugins/spring-beans-2.5.6.jar@start,\ reference\:file\:plugins/spring-context-2.5.6.jar@start,\ reference\:file\:plugins/spring-core-2.5.6.jar@start,\ reference\:file\:plugins/spring-osgi-core-1.2.1.jar@start,\ reference\:file\:plugins/spring-osgi-extender-1.2.1.jar@start,\ reference\:file\:plugins/spring-osgi-io-1.2.1.jar@start,\ reference\:file\:bundles/com.sntele.surfing.ability.datasource_1.0.0.201010081807.jar@start,\ reference\:file\:bundles/com.sntele.surfing.ability.demo_1.0.0.201010081807.jar@start osgi.bundles.defaultStartLevel=5 双击run.bat启动服务: 4.2 常用命令 命令 描述 install reference:file:所要安装的jar文件夹: /文件名@start 安装bundle start + 空格 + id(+空格+id…) 启动某个(或多个)bundle update + 空格 + id 更新某个bundle stop+ 空格 + id (+空格+id…) 停止某个(或多个)bundle uninstall + 空格 + id 卸载某个bundle ss 查看bundle状态 exit 退出 其他命令:在命令行输入help查看 五、常见问题 5 5.1 如何发布和引用远程服务 5.1.1 标准配置 1、 发布远程服务 • simple + jaxb 参考文档:http://cxf.apache.org/distributed-osgi-reference.html 注意:请注意加粗部分,采用这种方式服务将会侦听在跟jetty一样的默认端口8080, 发不是也不用指定特别的IP地址。 2、 引用远程服务 先在OSGI-INF/remote-services中建立一个xml文件如remote-service.xml,系统在自动 会自动构建服务并将服务注册到本地,内容如下: * pojo http://192.168.0.157:9002/com/sntele/surfing/ability/communication/sag/SmsCommunication 然后在META-INF/spring中建立文件servcie-reference-cxf.xml,将服务注如Spring中 内容如下: 做完如上工作后就可以在Spring的Bean配置中直接使用服务了。 5.1.2 自定义配置 • 方法一:(未采用) 将配置文件分离,加载一个配置bundle,这样在代码发布时就不会因为开发和测试时 同一个二进制发布包内有配置的不同。 为每个模块编写一个配置bundle • 方法二:(当前使用) 配置文件可以存放到有系统变量指定到的地方,如:-Dcom.sntele.surfing.config=..., 然后对配置文件建立相应的配置类来读取配置。如果没有指定配置路径则,默认在模块类路 径中存取,如:META-INF/conf中。 开发时可以在Eclipse的运行配置中的参数项加入-Dcom.sntele.surfing.config=...,配置 文件目前存在于com.sntele.surfing.ability.conf中 操作路径:Project->Properties->Run/Debug Settings选中当前使用的运行配置,点击 “Edit”,选择Arguments标签在VM arguments框中进行编辑。 • 方式三:(未采用) 如果OSGI可以从外部路径加载Spring配置文件,考虑将Spring的部分配置文件放置 在,运行时指定的路径中。如:-Dcom.sntele.surfing.config=...指定的路径中。 1、 应用远程服务 使用自定义配置将外部服务注册到本地JVM运行环境中,以便其它模块或者被Spring引用。 1)设置MANIFEST.MF Dependencies标签 Runtime标签 注:surfing-osgi-util-1.0.0.jar封装处理配置文件的工具包 2)编写配置文件放到-D制定的配置文件目录 3)编写Activator.java,加载服务 package com.sntele.surfing.ability.communication.sag.util; ... import com.sntele.surfing.osgi.util.ServiceUtils; import com.sntele.surfing.osgi.util.XmlConfiguration; ... public class Activator implements BundleActivator { private List srlst = new ArrayList(); @Override public void start(BundleContext bundleContext) throws Exception { // 加载配置文件 XmlConfiguration configuation = XmlConfiguration.getInstance("com.sntele.surfing.ability.communication.cxfsag.xm l"); // // 引用远程CXF服务 // List nodes = configuation.getList("/config/service- references/service"); ServiceUtils factory = new ServiceUtils(); for(Element node : nodes) { String interfaceClassName = node.getAttributeValue("interface"); String serviceUrl = node.getAttributeValue("url"); // 构造服务 Object service = factory.createService(interfaceClassName, serviceUrl); Logger.getLogger(Activator.class.getName()).info("成功构造远程服 务:" + interfaceClassName + "," + serviceUrl); // 注册服务为本地服务 ServiceRegistration sr = bundleContext.registerService(interfaceClassName , service, null); srlst.add(sr); Logger.getLogger(Activator.class.getName()).info("成功注册远程服 务到本地:" + interfaceClassName + "," + serviceUrl); } } } @Override public void stop(BundleContext arg0) throws Exception { // 注销服务 for(ServiceRegistration sr: srlst) { sr.unregister(); } } } 2、 发布远程服务 将本地服务发布为WebService。 1)IDE设置与引用远程服务一致 2)编写配置文件 3) 编写Activator.java,发布服务 ... public class Activator implements BundleActivator { ... @Override public void start(BundleContext bundleContext) throws Exception { ... // // 发布本地服务 // List publishedServices = configuation.getList("/config/service-publish/service"); for(Element node : publishedServices) { String interfaceClassName = node.getAttributeValue("interface"); String serviceUrl = node.getAttributeValue("url"); ... // 发布服务 ... } ... } ... } 5.2 OSGi manifest.mf 选项简介 Bundle-Activator 该类用于启动和停止绑定包。 Bundle-ClassPath 该属性指定要用于绑定包的 CLASSPATH。该属性可以包含对绑定包 jar 文件中目录或 jar 文件的引用。 Bundle-Version 该属性指定绑定包的版本号。包导入和必需的绑定包规范可以包括绑定包版本号。 Export-Package 该属性指定要公共暴露给其他插件的所有包。 Import-Package 该属性指定要从必需插件中显式导入的所有包。默认情况下,必须为要启动的绑定包解析所有包。还可以将包导入指定为可选项,以支持包不存在的情况。显式导入的类在 Require-Bundle 插件中的包之前解析。 Require-Bundle 该属性指定要在给定绑定包中导入使用的绑定包及其已导出的包。指定的绑定包在显式包导入之后解析。

下载文档,方便阅读与编辑

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 5 金币 [ 分享文档获得金币 ]
1 人已下载

下载文档

相关文档