阅读本节需要一些上下文知识,推荐阅读:
我们曾在 OSGi 理论: 模块元数据 (Bundle's manifest file) 中讨论过关于 OSGi bundle 元数据。这些元数据用于模块部署人员了解模块,以及 OSGi 运行时识别、连接模块和其约束性检查等。但在实践中我可能会遇到一些我们目标模块所依赖的 JARs 并没有写入这些元数据(比如:一些厂商的 JDBC Driver等),也就是说这些 JARs 不能直接用 OSGi 运行环境。这通常我们有以下几种方法来解决。
- 为其补充必要的元数据
- 将其合并打包到我们的目标模块中
- 作为 OSGi 系统包加载
在这里我们重点介绍第一种方式。其它两种方式由于模块共享重用和安全原因,在我们的实践中不太常用。
准备
Bnd 你可以在公共的 Maven Repository 获取
我们这里准备包装的是一个常用的 Apache POI - the Java API for Microsoft Documents
组织工作目录和资源文件
$ mkdir ~/bndspace && cd ~/bndspace
$ curl -L http://search.maven.org/remotecontent?filepath=biz/aQute/bnd/biz.aQute.bnd/3.1.0/biz.aQute.bnd-3.1.0.jar > bnd-3.1.0.jar
$ curl -L http://search.maven.org/remotecontent?filepath=org/apache/poi/poi/3.14/poi-3.14.jar > poi-3.14.jar
$ ls
bnd-3.1.0.jar poi-3.14.jar
查看原来的 manifest headers
$ java -jar bnd-3.1.0.jar print poi-3.14.jar
[MANIFEST poi-3.14]
Ant-Version Apache Ant 1.9.4
Built-By andreas.beeker
Created-By 1.6.0_45-b06 (Sun Microsystems Inc.)
Implementation-Title Apache POI
Implementation-Vendor The Apache Software Foundation
Implementation-Vendor-Id org.apache.poi
Implementation-Version 3.14
Manifest-Version 1.0
Specification-Title Apache POI
Specification-Vendor The Apache Software Foundation
Specification-Version 3.14
这是个常规的 JAR 元数据,并没有 bundle manifest headers,下面我们将为其添加我们需要的 bundle manifest headers
准备 bndfile,将以下内容存入 poi.bnd 文件中
ver: 3.14
-classpath: poi-${ver}.jar
Bundle-Vendor: The Apache Software Foundation
Bundle-Categroy: org.aves:wrapped:bundle
Bundle-Name: Apache POI
Bundle-DocURL: http://poi.apache.org/apidocs/index.html
Bundle-SymbolicName: org.aves.org.apache.poi
Bundle-Version: ${ver}
Export-Package: *;version=${ver}
Import-Package: *
-removeheaders:Implementation-Title,Implementation-Vendor,Implementation-Vendor-Id,Implementation-Version,Originally-Created-By,Require-Capability,Specification-Title,Specification-Vendor,Specification-Version,Tool,Ant-Version,Built-By,Created-By
-output: ${bsn}-${ver}.jar
bndfile 条目说明:
-
ver: 3.14
申明一个版本属性,以备后面引用。比如:Bundle-Version: ${ver}
-
Bundle-Vendor
,Bundle-Category
,Bundle-Name
,Bundle-DocURL
申明一些可阅读性信息 -
Bundle-SymbolicName
,Bundle-Version
申明模块识别符,(这里我们加了一个org.aves
的前缀,以示与原 JAR 的区别) -
Export-Package
,Import-Package
申明暴露的包和依赖的包 -
-removeheaders
删除一些冗余信息 -
-output
申明输入出文件名
包装 bundle
命令工具执行包装
$ java -jar bnd-3.1.0.jar bnd poi.bnd
$ ls
bnd-3.1.0.jar org.aves.org.apache.poi-3.14.jar poi-3.14.jar poi.bnd
我们得到了org.aves.org.apache.poi-3.14.jar
检视 org.aves.org.apache.poi-3.14.jar
bundle manifest headers
java -jar bnd-3.1.0.jar print org.aves.org.apache.poi-3.14.jar
[MANIFEST org.aves.org.apache.poi-3.14]
Bnd-LastModified 1459911809694
Bundle-Categroy org.aves:wrapped:bundle
Bundle-DocURL http://poi.apache.org/apidocs/index.html
Bundle-ManifestVersion 2
Bundle-Name Apache POI
Bundle-SymbolicName org.aves.org.apache.poi
Bundle-Vendor The Apache Software Foundation
Bundle-Version 3.14
Export-Package org.apache.poi;version="3.14"...
...
Import-Package javax.crypto,javax.crypto.spec,javax.imageio...
...
Manifest-Version 1.0
[IMPEXP]
Import-Package
javax.crypto
javax.crypto.spec
javax.imageio
...
...
org.w3c.dom
Export-Package
org.apache.poi {version=3.14, imported-as=[3.14,4)}
org.apache.poi.common.usermodel {version=3.14, imported-as=[3.14,4)}
org.apache.poi.ddf {version=3.14, imported-as=[3.14,4)}
...
...
org.apache.poi.wp.usermodel {version=3.14}
至此我可以将我包装的 POI bundle 部署于 OSGi 运行环境中了。其它的模块可通过它所暴露的包来引用相关类。同时我们可将这个 bundle 发布到我们私有的 Maven Repository 中供团队的其他人员使用
小结
整个过程都就是在为模块制作说明书,这和产品出厂配上说明有点类似。这有助于部署人员和 OSGi 环境了解模块并给予正确的处理。这样做的目的在前几节已经交代了,这里就不详述了。
有同学可能会担心我所依赖的库都要这样做吗?其实也不用担心了,如果你的依赖 JARs 大多来源于公共Maven Repository,这几年大部分的 JARs 都写入了 OSGi bundle manifest headers,所以这样包装过程不会太多。你也可以通前面所提到的其它两种方法进行引用依赖没有 bundle mainfest headers 的 JAR 文件。
Tip: 有很多 OSGi 的运行环境已经带有类似的 Wrapper 工具了,可直接通过它们自动完成 bundle 的包装。OSGi 的运行环境各有不同,其操作方法请参考它们的相关文档