初探OSGi Web容器:控制Web程序的生命周期
51CTO编辑推荐:OSGi入门与实践全攻略
这项工作非常有趣,因为 dm 服务器对 WAR 文件的支持已将近 18 个月;我们非常兴奋能够一起努力来推出一个标准。 作为终端用户,你将不再需要依靠专用的 API 接口或功能就可以在 OSGi 上部署 WAR 文件。SpringSource 负责编写 Web 容器的参考实现,过去几周,我一直在忙这件事。
本文讲述了 Web 容器规范最主要的内容以及编写 RI 代码所需的步骤。现在还不能提供规范文档,但我会概述其中最重要的要点。
目前,还没有发布 RI 的二进制文件,但通过从源文件进行创建是非常容易的。
Web 容器的主要功能
Web 容器所支持的最有趣的功能:
◆WAR 文件的安装
◆Web 应用程序组件(Web Application Bundles:缩写为 WAB)的安装
◆利用扩张器对 Web 应用程序生命周期的控制
◆利用 URL 参数对配置属性的控制
安装 WAR 文件
对我而言,Web 容器最有趣的功能是在 OSGi 上直接部署 WAR 文件而无需修改代码。(由于 JNDI 面前还未包含在规范中,因此使用的 JNDI 的 WAR 文件还需要修改代码。我认为这种限制不会一直存在,解决这个问题的工作正在进行。)
想要在 OSGi 上安装 WAR 文件,你只需在调用 BundleContext.installBundle 或使用平台的控制器时,在文件位置前添加 webbundle:。例如,在 Equinox 中可以这样做:
install webbundle:file:formtags.war |
当然,这要求 OSGi 平台已经部署 Web 容器。
Web 容器将对 WAR 执行多个转换,以确保获取了正常运行所需的符号名和版本以及必要的导入。为了添加 WEB-INF/classes 和WEB-INF/lib 中的所有文件,Web 容器还将更新组件路径。
安装 Web 应用程序组件(WAB)
如果你不想使用 Web 容器对 WAR 进行转换,完全可以跳过这个转换步骤。很简单,你可以忽略 webbundle 协议,自己直接添加相应的声明头文件并安装该组件。
在 WAR 套件路径下不能包含任何不属于 WEB-INF 的条目。这是为了防止用户的应用程序类在 Web 程序中显示为可见的资源文件。这可能为 WAR 带来更多限制,不过这个文问题正在解决。
利用扩展器控制生命周期
Web 容器使用控制器模型控制 Web 程序的生命周期。Web 应用程序在相应的组件启动时启动,并当该组件停止时停止。
在 Equinox 中,这意味着我可以直接从控制台启动或停止我的 Web 程序。例如,指定上述的 formtags.war 组件的组件 ID 为 50:
start 50 … Tomcat output … stop 50 |
使用 URL 参数控制配置
WAR 文件的配置可通过在安装 URL 后添加某些特定的配置属性来控制。
例如,为了控制 Web 程序的环境路径,你可以添加 Web-ContextPath 选项:
install webbundle:file:formtags.war?Web-ContextPath=ftags |
或者,为了控制生成的 Bundle-SymbolicName 头文件:
install webbundle:file:formtags.war?Bundle-SymbolicName=ftags.bundle |
Web 容器和 dm 服务器
Web 容器 RI 中代码大部分来自 dm 服务器中,或根据其中的代码改写,但是 RI 并不要求完整的 dm 服务器。我们会将 dm 服务器中当前的网页代码替换为 Web 容器 RI,另外,我们还会将 Web 容器作为在 OSGi 上创建 Web 程序的推荐方法。
参考实现介绍
Web 容器 RI 使用 Tomcat 作为 servlet 容器实现。RI 本身由四个组件构成。core bundle 包含所有独立于 servlet 容器的代码。tomcat 组件包含所有 Tomcat 专用代码。tomcat.fragment 组件包含缺省的 Tomcat 配置并作为碎片附加到 Tomcat Catalina 组件。extender bundle 包含所有扩展器行为,并且如果你选择手动管理 Web 程序的生命周期,可以将其删除。
创建引用实现
为了运行 RI,你需要从源文件中进行创建。源文件可以直接从 SVN 获取:
svn co https://anonsvn.springsource.org/svn/dm-server-osgi-web-container/trunk |
一旦获得了这些代码,你就可以使用以下命令进行创建:
cd build-web-container ant clean test collect |
如果测试失败,请使用 JIRA 提交故障。创建成功之后,你就可以运行 Web 容器并安装一些 WAR 文件。
运行参考实现
我使用 PAX Runner 运行 Web 容器 RI。我的 PAX Runner 配置利用创建的二进制文件和 Ivy 管理的相关性来运行 Web 容器。
在 build-web-container 目录中,你可以找到一个名为 runner.bundles 的文件。利用这个文件可指示 PAX Runner 安装 Web 容器需要的所有组件:
pax-run Cplatform=equinox Csnapshot runner.bundles |
该命令使用 PAX Runner 启动 Equinox。Csnapshot 标记用来指示 PAX Runner 下载 Equinox 最新的稳定版本――部署了最新公布的 OSGi 4.2 规范。
一旦 Equinox 启动并发出 ss 命令验证组件已经安装,你就可以看到所有已安装和运行的 45 个组件。
安装应用程序
我使用 dm 服务器的 FormTags WAR 示例进行测试。
我试图直接安装 FormTags 程序,但结果没有出现预期的结果:
install webbundle:file:formtags.war Bundle id is 48 start 48 |
运行启动之后,出现错误,显示与 org.xml.sax 包中某些类的 ClassNotFoundException 有关。
出现这种故障是因为在缺少情况下只为 WAR 文件提供了四个导入:
javax.servlet、javax.servlet.http、javax.servlet.jsp 和javax.servlet.tagext。
使用 Import-Package URL 参数就可以很容易地解决这个问题:
uninstall 48 install webbundle:file:/Users/robharrop/tmp/formtags.war?Import-Package= org.xml.sax,org.xml.sax.helpers,javax.xml.parsers,org.w3c.dom Bundle id is 49 start 49 |
这里我指定了 FormTags 程序所需的额外的包导入。这次程序成功启动,并且可以在浏览器中通过 http://localhost:8080/formtags 访问。
在 dm 服务器中,对于由系统组件导出的每个包,WAR 文件获得一个导入。这表示对于普通的系统包是自动可用的。我认为这是一个有用的功能。你是否也这样认为?或者更愿意手动控制对系统包的访问?
总结