Tomcat集成OSGI,并通过JNDI开放Web调用

Tomcat集成OSGi,首先要选择OSGI服务器,我这里采用的是equinox.jar.

第一步开发OSGI的bundle,这里就不说明了.
第二步构建OSGi在Tomcat下的目录结构如图${Tomcat_Home}/lib

[img]http://dl.iteye.com/upload/attachment/0077/3702/0c882e08-9dd8-3416-b788-df81e8a05d5f.jpg[/img]
第三步配置OSGI启动项,配置文件[config.ini]内容如下:

osgi.noShutdown=true
osgi.bundles=reference\:file\:bundles/org.apache.commons.logging_1.0.4.v201101211617.jar@start,reference\:file\:bundles/org.eclipse.osgi.services_3.3.0.v20110513.jar@start,reference\:file\:bundles/DictQuery_1.0.0.jar@start,reference\:file\:bundles/RomoteDictQuery_1.0.0.jar@start,reference\:file\:bundles/LocalDictQuery_1.0.0.jar@start
osgi.bundles.defaultStartLevel=4

第四步关键了,我们把OSGI的生命周期集成到Tomcat容器来管理.

package standard.osgi.jndi;

import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.catalina.Lifecycle;
import org.apache.catalina.LifecycleEvent;
import org.apache.catalina.LifecycleListener;
import org.eclipse.core.runtime.adaptor.EclipseStarter;
import org.osgi.dictquery.query.QueryService;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;

public class OsgiListener implements LifecycleListener {

private static Logger log = Logger.getLogger(OsgiListener.class.getName());

private String osgiType = "Equinox";

private BundleContext bundleContext;

private static OsgiListener listener = null;

public static OsgiListener getInstance(){
return listener;
}

public BundleContext getBundleContext() {
return bundleContext;
}

public void setBundleContext(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}

@Override
public void lifecycleEvent(LifecycleEvent event) {
if (Lifecycle.AFTER_INIT_EVENT.equals(event.getType())) {
log.info("The osgi content is initialized. Using osgi content:"+ osgiType);
try {
// initContent();
} catch (Exception e) {
log.log(Level.SEVERE, "初始化osgi失败"+e.getCause());
}

} else if (Lifecycle.START_EVENT.equals(event.getType())) {

try {

log.info("Starting osgi service.");

EclipseStarter.run(new String[] { "-console" }, null);
initContent();
log.info("Starting osgi service invoke.");
//获取服务
//this interface is not the osgi's interface.
// QueryService queryService = null;
Object queryService = null;
ServiceReference serviceRef = bundleContext.getServiceReference(QueryService.class.getName());
if(null != serviceRef){
queryService = bundleContext.getService(serviceRef);
}
Method method = queryService.getClass().getDeclaredMethod("queryWorld", String.class);
Object result = method.invoke(queryService, "sky");
System.out.println("11Result is " +new String(result.toString().getBytes(),"GB2312"));

} catch (Exception e) {

e.printStackTrace();

log.info("Starting the osgi content occured error. "

+ e.getMessage());

}

} else if (Lifecycle.STOP_EVENT.equals(event.getType())) {

try {

log.info("Stopping osgi service.");

EclipseStarter.shutdown();

} catch (Exception e) {
log.info("Stopping the osgi content occured error. "

+ e.getMessage());

}

}

}

/**
* 初始化osgi
*/
private void initContent() {
bundleContext = EclipseStarter.getSystemBundleContext();
listener = this;
}

}


在web容器启动的时候,启动osgi容量,这里提供了一个简单的调用,通过bundleContext可以获取服务,通过反映可以调用osgi方法,并返回结果.[osgi classLoader is not the web classloader].
启动Tomcat,你会发现启动成功,并成功启动osgi容器,调用成功osgi容量的方法.
当然,这里的bundleContext是可以通过JNDI开放到Tomcat容器下的其他web应用使用的.
那么如何把OSGI包装成JNDI开放出去呢

第一步,开发InitialContext

package standard.osgi.jndi;

import java.util.HashMap;
import java.util.Hashtable;

import javax.naming.InitialContext;
import javax.naming.NamingException;

public class MyInitialContext extends InitialContext {

private static HashMap<String, Object> map = new HashMap<String, Object>();

public MyInitialContext() throws NamingException {
super();
}

public MyInitialContext(Hashtable<?,?> environment) throws NamingException {
super(environment);
}

@Override
public void bind(String name, Object obj) throws NamingException {
map.put(name, obj);
}

@Override
public void unbind(String name) throws NamingException {
map.remove(name);
}

@Override
public Object lookup(String name) throws NamingException {
return map.get(name);
}
}


第二步,开发InitialContextFactory

package standard.osgi.jndi;

import java.util.Hashtable;

import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.spi.InitialContextFactory;

public class MyInitialContextFactory implements InitialContextFactory{

@Override
public Context getInitialContext(Hashtable<?, ?> environment)
throws NamingException {
return new MyInitialContext();
}

}



第三步,使用我们自定义的JNDI注册我们的OSGI服务,修改上面的initContext方法

/**
* 初始化osgi
*/
private void initContent() {
bundleContext = EclipseStarter.getSystemBundleContext();
try {
Hashtable env = new Hashtable();
//env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");
env.put(Context.INITIAL_CONTEXT_FACTORY, "standard.osgi.jndi.MyInitialContextFactory");
Context ctx = new InitialContext(env);
ctx.bind("init/context", bundleContext);
} catch (NamingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

第四步,这样我们的osgi的bundleContext已经注册到Jndi中了,我们要web中,只需要获取我们自定义的JNDI,获取bundleContext就可以了.

Hashtable env = new Hashtable();
//env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");
env.put(Context.INITIAL_CONTEXT_FACTORY, "standard.osgi.jndi.MyInitialContextFactory");
Context ctx = new InitialContext(env);
BundleContext bundleContextJndi = (BundleContext)ctx.lookup("init/context");
Object queryService = null;
ServiceReference serviceRef = bundleContextJndi.getServiceReference(QueryService.class.getName());
if(null != serviceRef){
queryService = bundleContextJndi.getService(serviceRef);
}
Method method = queryService.getClass().getDeclaredMethod("queryWorld", String.class);
Object result = method.invoke(queryService, "sky");
System.out.println("jndi Result is " +new String(result.toString().getBytes(),"GB2312"));


这里没作太多的封装,不过成功的把OSGI封装到Tomcat,再把OSGI通过JNDI开放到各个web应用。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值