设为首页 加入收藏

TOP

Java Web应用集成OSGI
2018-01-22 17:24:36 】 浏览:257
Tags:Java Web 应用 集成 OSGI

就像Java Web应用程序需要运行在Tomcat、Weblogic这样的容器中一样。程序员开发的OSGI程序包也需要运行在OSGI容器中。目前主流的OSGI容器包括:Apache Felix以及Eclipse Equinox。OSGI程序包在OSGI中称作Bundle
Bundle的整个生命周期都交与OSGI容器进行管理。可以在不停止服务的情况下,对Bundle进行加载和卸载,实现热部署。
Bundle对于外部程序来说就是一个黑盒。他只是向OSGI容器中注册了供外部调用的服务接口,至于实现则对外部不可见。不同的Bundle之间的调用,也需要通过OSGI容器来实现。


刚才说到Bundle是一个黑盒,他所有实现都包装到了自己这个“盒子”中。在开发Bundle时,避免不了引用一些比如Spring、Apache commons等开源包。在为Bundle打包时,可以将当前Bundle依赖jar与Bundle的源码都打包成一个包(all-in-one)。这种打包结果就是打出的包过大,经常要几兆或者十几兆,这样当然我们是不可接受的。下面就介绍一种更优的做法。


Bundle可以在MANIFEST.MF配置文件中声明他要想运行起来所要的包以及这些包的版本 !!!而OSGI容器在加载Bundle时会为Bundle提供Bundle所需要的包 !!!在启动OSGI容器时,需要在OSGI配置文件中定义org.osgi.framework.system.packages.extra,属性。这个属性定义了 OSGI容器能提供的包以及包的版本。OSGI在加载Bundle时,会将他自己能提供的包以及版本与Bundle所需要的包以及版本列表进行匹配。如果匹配不成功则直接抛出异常:


也可能加载Bundle通过,但是运行Bundle时报ClassNotFoundException。这些异常都由于配置文件没配置造成的。理解了配置文件的配置方法,就能解决60%的异常。


BundleImport-Package属性中通过以下格式配置:


语法与Impirt-Package基本一致,只是org.osgi.framework.system.packages.extra不支持通配符。


在我们平时开发中有些情况下加载一个Class会使用this.getClassLoader().loadClass。但是通过这种方法加载Bundle中所书写的类的class会失败,会报ClassNotFoundException。在Bundle需要使用下面的方式来替换classLoader.loadClass方法


由于Bundle加载Class的特性,会导致在加载Spring配置文件时报错。所以需要将Spring启动所需要的ClassLoader进行更改,使其调用BundleContext.loadClass来加载Class。


这里选用了Apache Felix来开发,主要是因为Apache Felix是Apache的顶级项目。社区活跃,对OSGI功能支持比较完备,并且文档例子比较全面。
其实OSGI支持两种方式来部署Bundle


从项目的整体考虑,我们选用了第二种方案。


开发Bundle时,首先需要开发一个BundleActivator。OSGI在加载Bundle时,首先调用BundleActivatorstart方法,对Bundle进行初始化。在卸载Bundle时,会调用stop方法来对资源进行释放。


start方法中调用context.registerService来完成对外服务的注册。


通过上面的配置,只是将OSGI容器加载到了Web应用中。还需要修改Web应用程序路由的代码。


Apache Felix例子中提供的ProvisionActivator,只会在系统启动时加载/WEB-INF/bundles/目录下的Bundle。当文件夹下的Bundle文件有更新时,并不会自动更新OSGI容器中的Bundle。所以Bundle自动加载的逻辑,需要我们自己增加。下面提供实现的思路:


最后一个问题,通过上面的方式,可以实现Bundle的自动加载。但是刚才我们介绍了,在路由程序中,我们会缓存OSGI容器中所有的Bundle所对应的ServiceReference以及所有Bundle所对应的servlet-pattern。所以Bundle自动更新后,我们还需要将路由程序中的缓存同步的进行更新。
可以通过向bundleContext中注册BundleListener,当OSGI容器中的Bundle状态更新后,会调用BundleListenerbundleChanged回调方法。然后我们可以在bundleChanged回调方法中书写更新路由缓存的逻辑


】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇浅识Cortex-M3 的双堆栈机制 下一篇Python实现求最长子串长度

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目