在osgi的环境下,我们需要RMI的方式调用远端的服务的话,一般有以下的方案。
步骤如下:
服务端发布webserivce,这个我直接摘录网上的资料,代码如:
接口:
public interface DisplayService {
boolean displayText(String text);
String getID();
}
实现类:
public class DisplayServiceImpl implements DisplayService {
private final String id;
public DisplayServiceImpl(String id) {
this.id = id;
System.out.println("Created DisplayService [" + id + "]");
}
public boolean displayText(String text) {
System.out.println("DisplayService [" + id + "]: " + text);
return true;
}
public String getID() {
return id;
}
}
发布服务:
public class Activator implements BundleActivator {
private ServiceRegistration reg;
public void start(BundleContext bc) throws Exception {
Dictionary props = new Hashtable();
String host = getHostName(); // obtain the current host name
int port = getPort(); // find a free port
props.put("service.exported.interfaces", "*");
props.put("service.exported.configs", "org.apache.cxf.ws");
props.put("org.apache.cxf.ws.address", "http://" + host + ":" + port + "/display");
reg = bc.registerService(DisplayService.class.getName(),
new DisplayServiceImpl(host + ":" + port), props);
}
public void stop(BundleContext bc) throws Exception {
reg.unregister();
}
}
客户端代码,如果使用了springDM则配置如下:
第一步:先在OSGI-INF\remote-service目录下配置remote-services.xml内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<endpoint-descriptions xmlns="http://www.osgi.org/xmlns/rsa/v1.0.0">
<endpoint-description>
<property name="objectClass">
<array>
<value>org.apache.cxf.dosgi.samples.springdm.DinnerService</value>
</array>
</property>
<property name="endpoint.id">http://localhost:9000/org/apache/cxf/dosgi/samples/springdm/DinnerService</property>
<property name="service.imported.configs">org.apache.cxf.ws</property>
</endpoint-description>
</endpoint-descriptions>
第二步:在spring配置文件中配置如下:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:osgi="http://www.springframework.org/schema/osgi"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd">
<osgi:reference id="dinnerServiceRef" interface="org.apache.cxf.dosgi.samples.springdm.DinnerService"/>
<bean class="org.apache.cxf.dosgi.samples.springdm.client.DinnerServiceConsumer"
init-method="start">
<property name="dinnerService" ref="dinnerServiceRef"/>
</bean>
</beans>
调用端的代码,如下:
public class DinnerServiceConsumer {
DinnerService dinnerService;
public void setDinnerService(DinnerService ds) {
dinnerService = ds;
}
public void start() {
System.out.println("Found the following restaurants:");
for (Restaurant r : dinnerService.findRestaurants("nice and not too expensive!")) {
System.out.format(" %s (%s) Rating: %d\n", r.getName(), r.getAddress(), r.getRating());
}
}
}
如果没有使用SpringDM则和普通的OSGI服务发现方式一样,获取webserivce调用服务方式如下:
public class Activator implements BundleActivator {
private ServiceTracker tracker;
private Map<DisplayService, String> displays = new ConcurrentHashMap<DisplayService, String>();
private ScheduledExecutorService scheduler;
private ScheduledFuture<?> handle;
public void start(BundleContext bc) throws Exception {
tracker = new ServiceTracker(bc, DisplayService.class.getName(), null) {
public Object addingService(ServiceReference reference) {
Object svc = super.addingService(reference);
if (svc instanceof DisplayService) {
DisplayService d = (DisplayService) svc;
System.out.println("Adding display: " + d.getID() + " (" + d + ")");
displays.put(d, d.getID());
}
return svc;
}
public void removedService(ServiceReference reference, Object service) {
String value = displays.remove(service);
System.out.println("Removed display: " + value);
super.removedService(reference, service);
}
};
tracker.open();
scheduler = Executors.newScheduledThreadPool(1);
Runnable printer = new Runnable() {
int counter;
public void run() {
counter++;
String text = "some text " + counter;
System.out.println("Sending text to displays: " + text);
for (Entry<DisplayService, String> entry : displays.entrySet()) {
try {
entry.getKey().displayText(text);
} catch (Throwable th) {
System.out.println("Could not send message to display: " + entry.getValue());
}
}
}
};
handle = scheduler.scheduleAtFixedRate(printer, 5, 5, TimeUnit.SECONDS);
}
public void stop(BundleContext bc) throws Exception {
handle.cancel(true);
tracker.close();
}
}
注意,一定要加入cxf-dosgi-ri-discovery-local-xxx.jar这个jar包以及其他相关的包,具体可以参考网站:
http://cxf.apache.org/dosgi-discovery-demo-page.html,而且我这个也是参考官方的例子,如果要参考比较全的例子,可以下载官方的源码,里边的samples下有各种例子,比如如何使用spring-dm整合,如何发布到zookeeper上等等。