OSGI bundle工程

在学完《走近Java模块化系统OSGi》后我们已对osgi有初步的印象,今天我们将从一个hello world来具体地接触osgi。

我们将采用maven来构建一个简单的bundle,不熟悉maven的同学请先了解一下再继续。我们还会使用servicemix来做运行时平台,至于IDE,则不限。

首先是maven项目的pom.xml,如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:pom="http://maven.apache.org/POM/4.0.0">
    <modelVersion>4.0.0</modelVersion>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <groupId>com.ponder.Demo</groupId>
    <artifactId>demo1</artifactId>
    <packaging>jar</packaging>
    <version>1.0</version>
    <name>Demo:demo1:1.0</name>
    <url>http://Demo.ponder.com/demo1/</url>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.4</version>
                <configuration>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <classpathPrefix>lib/</classpathPrefix>
                        </manifest>
                        <manifestEntries>
                            <Class-Path>${project.build.finalName}.jar</Class-Path>
                            <Built-By>Ponder</Built-By>
                            <Bundle-ManifestVersion>2</Bundle-ManifestVersion>
                            <Bundle-Name>${project.groupId}.${project.ArtifactId}</Bundle-Name>
                            <Bundle-SymbolicName>${project.name}</Bundle-SymbolicName>
                            <Bundle-Version>${project.version}</Bundle-Version>
                            <Bundle-Vendor>${project.groupId}</Bundle-Vendor>
                            <Bundle-Activator>com.ponder.Demo.demo1.activator</Bundle-Activator>
                            <Export-Package>com.ponder.Demo.demo1;version="1.0"</Export-Package>
                            <Import-Package>org.osgi.framework</Import-Package>
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.6.4</version>
            <type>jar</type>
        </dependency>
        <dependency>
            <groupId>org.osgi</groupId>
            <artifactId>org.osgi.core</artifactId>
            <version>4.2.0</version>
            <type>jar</type>
        </dependency>
    </dependencies>
</project>

在这个POM里,我们使用了Maven-jar-plugin插件,这个插件在这个课程中十分重要,它负责了OSGI bundle的Manifest.mf的构建。

而另一个选择就是Maven-Bundle-plugin,也能实现同样的目的,而且更强大,甚至能够自动生成bundle的manifest.mf里的数据项,但我不推荐,因为我认为Manifest.mf里的数据项的定制是一个设计问题,我们不能指望一个机器去“艺术地”设计,而Maven-jar-plugin给我们更大的自由度,更"纯粹"。

OSGI Activator

我们先定义一个类com.ponder.Demo.demo1.activator:

package com.ponder.Demo.demo1;

import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

/**
 *
 * @author han
 */
public class activator implements BundleActivator{

    @Override
    public void start(BundleContext context) throws Exception {
       System.out.println("Hello world!");
    }

    @Override
    public void stop(BundleContext context) throws Exception {
       System.out.println("Stop bundle!");
    }

}

这个类实现了OSGI的BundleActivator接口,这个接口有两个方法:start和stop,顾名思义,start就是bundle在启动时需执行的方法,而stop则是bundle停止时需执行的方法。

我们可以回头看看OSGi入门,关于bundle的生命周期的图,可以帮助我们理解activator的意义。

lifecycle2.png

下面,我们尝试构建这个bundle,利用maven的mvn package指令,我们可以得到一个jar包:demo1-1.0.jar

我们再从http://servicemix.apache.org 下载一个Servicemix,目前稳定版本是5.4.0;在文件夹里解压servicemix,我们可以看到servicemix的目录结构:

servicemixfolder.png

我们将demo1-1.0.jar放到deploy文件夹里,然后运行bin\servciemix.bat( windows)或bin/servicemix(linux).

demo1run.png

从上图,我们可以看到出现了“Hello world!"的字样,这个是activator的start方法的执行结果。

我们输入一个命令:list ,可以列出当前部署在servicemix上的bundle,我们部署的bundle demo1也在其中,每个bundle的前面都有一个bundle ID, 现在demo1的bundle ID是211

我们再输入一个命令:stop 211 ,就可以停止demo1这个bundle,我们可以看出,它执行了activator里的stop方法,输出了 “stop bundle!"的字样。

demo1-2.jpg

我们再执行一次list命令,可以看到bundle从原来的Active状态变成了Resolved的状态。

demo1-3.png

最后,我们用压缩软件(winrar、winzip)打开demo1-1.0.jar,从包里的META-INF里,可以找到一个MANIFEST.MF文件,查看一下MANIFEST.MF:

demo1-4.png

大家可以参照以上屏幕截图,结合manifest.mf文件的内容,理解一下manifest.mf的作用.

登录发表评论 注册

反馈意见