基于OSGi和Spring开发Web应用简介:作为一个新的事实上的工业标准,OSGi已经受到了广泛的关注,其面向服务(接口)的基本思想和动态模块部署的能力,是企业级应用长期以来一直追求的目标。Spring是一个著名的轻量级J2EE开发框架,其特点是面向接口编程和非侵入式的依赖注入。将OSGi和Spring结合能充分发挥二者各自的特长,更好地满足企业级应用开发的需求。Spring开发组织在2008年发布了将OSGi和Spring结合的第一个版本:Spring-DM。本文通过一个简单实例,介绍如何利用Spring-DM开发基于OSGi和Spring架构的Web应用,同时探讨其中用到的关键技术及其基本思想。开发一个简单的OSGiWeb应用实例一个简单的Web应用我们写一个简单的Web应用compute.html:计算两个数字的和或乘积。如下图所示:图1.一个简单例子为了体现OSGibundle的动态部署能力,我们写两个servicebundle,其中一个计算两个数字的和(称为addbundle),另外一个计算两个数字的积(称为multiplybundle)。当我们点击“Compute”按钮的时候,如果此时addbundle被部署,则页面将返回两个数字的和,否则如果此时multiplybundle被部署,则页面将返回两个数字的积。开发环境准备下载Eclipse3.4获取所有OSGi,Equinox和Spring的插件,如下图所示:图2.相关插件列表打开Eclipse,设置targetplatform为上述插件集合基本模块设计该应用主要包含两个层次:服务层和Web层。Web层基于Spring-MVC实现,包含处理Web访问相关的bundle(本例中只有一个)。服务层包含处理数字计算的bundle,本例中包含一个声明服务接口的computeinterfacebundle和两个实现该服务接口的bundle:addbundle和multiplybundle。基本模块结构如下图所示:图3.基本框架模块程序实现Step1:实现ServiceLayer服务层的三个OSGibundle实现完毕之后如下图所示:图4.服务层服务层.bmp其中com.zxn.example.service.compute是声明服务接口的bundle。com.zxn.example.service.compute.add和com.zxn.example.service.compute.multiply是实现了服务接口的两个bundle。com.zxn.example.service.compute声明一个Compute接口,其中包含一个接口方法computeNums(),如下图所示:图5.服务层接口bundlecom.zxn.example.service.compute.addbundlecom.zxn.example.service.compute.add的基本程序结构如下图所示:图6.接口实现bundle:add在该addbundle中,添加一个Add类,实现Compute接口,如下图所示:图7.接口实现代码:Add类注意到我们在META-INF下建了一个spring目录,并且添加了一个computeAdd-context.xml文件。系统启动时,Spring将利用该xml文件创建一个bean实例,并把该bean输出为一个OSGiservice,如下图所示:图8.Spring声明文件:computeAdd-context.xml该xml文件中,osgi:service是Spring-DM输出OSGiservice的标记,其中的interface属性标明了该service实现的服务接口。com.zxn.example.service.compute.multiply按照与addbundle同样的方法,实现multiplybundle,如下图所示:图9.接口实现代码:Multiply类接口实现代码-Multiply类.bmp类似的,添加一个computeMultiply-context.xml输出OSGiservice,如下图所示:图10.Spring声明文件:computeMultiply-context.xmlStep2:实现WebLayerWeb层只包含一个bundle:com.zxn.example.web,采用Spring-MVC和OSGi构建,基本程序结构如下图所示:图11.WebLayer程序结构ComputeControler.java该JAVA类实现了org.springframework.web.servlet.mvc.Controller,是本web应用中核心的servlet,负责接受并处理web请求。该类调用ComputeServiceRef的方法实现业务逻辑。该类关键的方法是handleRequest(…),如下图所示:图12.核心servlet类ComputeServiceRef.java该JAVA类负责引用部署的servicebundle完成最终计算,其中的computeService由Spring根据OSGi中实际部署的service进行注入。本例中,实际部署的service可能是addbundle或者multiplybundle。需要特别注意的是,此处体现了Spring-DM的动态特性。OSGi的动态部署能力使得Spring的动态服务注入成为可能。图13.服务消费类HTTPContextResgistry.java该JAVA类负责在OSGi环境中配置和注册HTTP服务,其关键方法为bean初始化时调用的init()方法。图14.在OSGi环境中注册HTTP服务该init方法中,第六行的getHTTPService(…)调用OSGi的ServiceTracker来获取OSGi环境中注册的HTTP服务的引用,如下图所示:图15.使用ServiceTracker获取HTTP服务computeWeb-context.xml该xml文件主要用于配置HTTPContextResgistrybean类,以及导入对Compute服务接口的引用。标记osgi:reference用于声明要导入的服务接口,其interface属性标明了该接口的定义,本例中为com.zxn.example.service.compute.Compute接口。图16.Spring声明文件:导入服务接口computeWeb-Dispatcher.xml该xml文件用于配置ComputeControlerbean类。图17.Spring声明文件:配置核心servlet类回页首运行程序以往开发J2EE应用通常需要将应用服务器的runtime集成到开发环境中才能进行程序调试,非常麻烦。基于OSGi的应用完全可以脱离应用服务器运行,这使得程序开发和调试变得非常容易,直接在Eclipse中调试运行就可以。我们在Eclipse中将程序运行起来,如下图所示:图18.运行OSGi程序从上图中看到,我们同时选择部署了addbundle和multiplybundle,利用OSGiconsole察看如下:图19.察看部署的OSGibundle当OSGi环境中同时部署有多个服务接口的实现bundle时,OSGi会选择一个默认的bundle提供服务。本例中,Spring会默认注入addbundle。我们通过web访问compute.html页面:图20.访问页面点Compute按钮之后,结果页面如下:图21.访问结果可以看出,是addbundle提供了计算服务。下面我们通过命令<stop76>来停止addbundle的服务:图22.停止addbundle图23.addbundle状态变为RESOLVED重新访问compute.html页面,结果得到的是两个数字的乘积。可以看出,是multiplybundl提供了计算服务。如下图所示:图24.再次访问页面回页首小结作为当前颇具生命力的两个标准和框架,OSGi和Spring已经初步融合在一起。二者的结合,为开发企业级的Web应用同时提供了巨大的灵活性和动态部署能力。本文通过一个简单的例子,描述如何开发一个基于OSGi和Spring的Web应用,并说明了开发过程中涉及到的技术关键点。OSGI开发web应用开发web的两种方式基于OSGI开发B/S应用有两种方式:1)在OSGI框架中嵌入Http服务器2)在Servlet容器中嵌入OSGI框架Http服务器嵌入到OSGI框架环境配置配置运行环境,选择Run-RunConfiguration,new一个环境保留以下几个Bundle,包括javax.servlet、org.apache.commons.logging、org.eclipse.equinox.http.jetty、org.eclipse.equinox.http.servlet、org.eclipse.osgi、org.eclipse.osgi.services、org.mortbay.jetty其它的都不选择如果出现异常,比如说明端口被占用,在RunConfiguration中设置参数重新运行,如果没有出现异常,则表示运行成功。在osgi窗口输入ss,会看到如下结果打开浏览器输入,得到结果如下:OSGI开发web应用在Eclipse中OSGi程序的开发是以插件工程的方式进行开发的。首先新建插件工程HelloWebOSGI完成后选择下一步在模板中选择HelloOSGIBundle选择下一步“BasicOSGiBundle”对话框,是模板需要输入的Bundle启动和停止时列印的消息内容,在此保留默认,点“Finish”。在左侧的包浏览面板中可以看到OSGi工程的结构,“Plug-inDependencies”下是OSGi插件运行需要的组件,src目录下是自动生成的源代码,simplewebosgi.Activator是Bundle生成周期管理类,可以监听组件的启动和停止动作。与普通Java工程所不同的是向导会生成“META-INF”目录以及其下的文件MANIFEST.MF文件,此文件会随插件的发布一起被打到jar包中,定义了Bundle的标识、版本、名称、运行环境等内容。右边是可视化的配置管理器,在这里可以定义插件,配置插件运行所依赖的组件及需要导入的包,运行时环境,编译构建配置等。然后在src下新建目录page,在page目录下建立hello.html,加入内容?!DOCTYPEhtmlPUBLIC-//W3C//DTDHTML4.01Transitional//EN=Content-Typecontent=text/html;charset=UTF-8titleatestpage/title/headbodyHello,Thisisatestpage!/body/html在工程中引入javax.servlet、javax.servlet.http、org.osgi.service.http这几个包,如下图所示现在虽然HTML页面文件有了,包也配置好了,但是还不能通过HTTP访问相应的页面,如果现在测试运行访问服务,浏览器会提示找不到页面,我们需要将页面注册到OSGiHttp服务中修改生成的Activator类,注册加入HttpService服务,程序如下:?packagehellowebosgi;importorg.osgi.framework.BundleActivator;importorg.osgi.framework.BundleContext;importorg.osgi.framework.ServiceReference;importorg.osgi.serv