发布和使用服务
由于 OSGi 框架能够方便的隐藏实现类,所以对外提供接口是很自然的事情,OSGi 框架提供了服务的注册和查询功能。好的,那么我们实际操作一下,就在 Hello world 工程的基础上进行。
我们需要进行下列的步骤:
- 定义一个服务接口,并且 export 出去供其它 bundle 使用;
- 定义一个缺省的服务实现,并且隐藏它的实现;
- Bundle 启动后,需要将服务注册到 felix 框架;
- 从框架查询这个服务,并且测试可用性。
直接上代码,主pom的xml文件
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.renming.osgi.helloworld</groupId>
<artifactId>helloworld</artifactId>
<version>1.0.0</version>
<modules>
<module>server</module>
<module>client</module>
</modules>
<packaging>pom</packaging>
<name>helloworld</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.renming.osgi.helloworld</groupId>
<artifactId>server</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse</groupId>
<artifactId>osgi</artifactId>
<version>3.9.1-v20130814-1242</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
server的pom文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>helloworld</artifactId>
<groupId>com.renming.osgi.helloworld</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>server</artifactId>
<packaging>bundle</packaging>
<name>server</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.eclipse</groupId>
<artifactId>osgi</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.4.0</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-Version>${project.version}</Bundle-Version>
<Bundle-SymbolicName>$(replace;${project.artifactId};-;_)</Bundle-SymbolicName>
<Export-Package>
com.renming.osgi.helloworld.server.inter;version="${project.version}"
</Export-Package>
<Import-Package>org.osgi.framework</Import-Package>
<Bundle-Activator>com.renming.osgi.helloworld.Activator</Bundle-Activator>
</instructions>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
client的pom文件
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>helloworld</artifactId>
<groupId>com.renming.osgi.helloworld</groupId>
<version>1.0.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>client</artifactId>
<packaging>bundle</packaging>
<name>client</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.renming.osgi.helloworld</groupId>
<artifactId>server</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse</groupId>
<artifactId>osgi</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.4.0</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-Version>${project.version}</Bundle-Version>
<Bundle-SymbolicName>$(replace;${project.artifactId};-;_)</Bundle-SymbolicName>
<Import-Package>
org.osgi.framework,com.renming.osgi.helloworld.server.inter;version="${project.version}"
</Import-Package>
<Bundle-Activator>com.renming.osgi.helloworld.Activator</Bundle-Activator>
</instructions>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
server的java代码目录如下:
clent的java代码目录如下:
其中server中的Activator的java代码如下:
package com.renming.osgi.helloworld;
import java.util.ArrayList;
import java.util.List;
import com.renming.osgi.helloworld.server.impl.HelloImpl;
import com.renming.osgi.helloworld.server.inter.Hello;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
public class Activator implements BundleActivator {
private List<ServiceRegistration> registrations = new ArrayList<ServiceRegistration>();
private static BundleContext context;
static BundleContext getContext() {
return context;
}
@Override
public void start(BundleContext bundleContext) throws Exception {
Activator.context = bundleContext;
System.out.println("----------------hello start---------------------");
//注册hello接口中的服务
registrations.add(bundleContext.registerService(Hello.class.getName(), new HelloImpl("Hello, OSGi"), null));
System.out.println("----------------hello start---------------------");
}
@Override
public void stop(BundleContext bundleContext) throws Exception {
Activator.context = null;
for (ServiceRegistration registration : registrations) {
System.out.println("unregistering: " + registration);
registration.unregister();
}
}
}
clent中的Activator的java代码如下:
package com.renming.osgi.helloworld;
import com.renming.osgi.helloworld.server.inter.Hello;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
public class Activator implements BundleActivator {
@Override
public void start(BundleContext ctx) {
System.out.println("----------------hello client start---------------------");
ServiceReference ref = ctx.getServiceReference(Hello.class.getName());
if (ref != null) {
Hello hello = null;
try {
hello = (Hello) ctx.getService(ref);
if (hello != null) {
hello.sayHello();
}else {
System.out.println("Service:Hello---object null");
}
} catch (RuntimeException e) {
e.printStackTrace();
} finally {
ctx.ungetService(ref);
hello = null;
}
} else {
System.out.println("Service:Hello---not exists");
}
System.out.println("----------------hello client start---------------------");
}
@Override
public void stop(BundleContext ctx) throws Exception {
}
}
server中主要是对某个服务进行注册的操作,其中注册的方法主要如下:
//注册hello接口中的服务
registrations.add(bundleContext.registerService(Hello.class.getName(), new HelloImpl("Hello, OSGi"), null));
实际注册的是hello接口的实现类HelloImpl
OSGI的运行:
这里我们采用的是felix的具体实现的OSGI
下载felix https://mirrors.tuna.tsinghua.edu.cn/apache//felix/org.apache.felix.main.distribution-6.0.0.zip
拷贝bin、bundle、conf到当前工程,也可自行建目录。
运行felix项目:java -jar bin/felix.jar
若未报错并出现g!。然后执行命令行 lb 得到如下控制台输出信息。
安装如上项目打包好的文件 server-1.0.0.jar、clent-1.0.0.jar
最后控制台输出Hello, OSGI。由此一个简单的基于OSGI框架的服务注册和发现。