發佈和使用服務
由於 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框架的服務註冊和發現。