您的想法非常正确,我们有一个模块化的Web应用程序,其中应用程序本身是从独立组件(OSGi包)自动组装而成的,每个包都会贡献自己的页面、资源、css和可选的javascript。
我们不使用JSF(这里使用的是Spring MVC),因此我无法评论该框架在OSGi上下文中增加的复杂性。
大多数框架或方法仍然坚持“旧”的思维方式:一个WAR文件代表您的Web应用程序,然后有许多OSGi包和服务,但几乎没有关注GUI本身的模块化。
设计先决条件
对于OSGi来说,需要解决的第一个问题是:您的部署方案是什么,主要容器是谁?我的意思是,您可以在OSGi运行时上部署应用程序,并使用其基础设施进行一切。或者,您可以将OSGi运行时嵌入传统的应用服务器中,然后您需要重用一些基础设施,特别是您想要使用AppServer的servlet引擎。
我们的设计目前基于OSGi作为容器,我们使用OSGi提供的HTTPService作为servlet容器。我们正在研究在外部servlet容器和OSGi HTTPService之间提供某种透明桥接的方法,但这项工作仍在进行中。
Spring MVC + OSGi模块化Web应用程序的架构草图
因此,目标不仅是通过OSGi提供Web应用程序,而且还要将OSGi的组件模型应用于Web UI本身,使其可组合、可重用、动态。
以下是系统中的组件:
- 1个中央包,负责将Spring MVC与OSGi连接起来,具体而言,它使用Bernd Kolb的代码(链接:http://thegoodthebadtheugly.wordpress.com/2007/05/20/springosgi/ )允许您将Spring DispatcherServlet作为servlet向OSGi注册。
- 1个自定义URL Mapper,注入到DispatcherServlet中,并提供将传入的HTTP请求映射到正确控制器的映射。
- 1个基于Sitemesh的中央JSP装饰器定义了站点的全局布局,以及我们想要提供作为默认值的中央CSS和Javascript库。
每个想要贡献页面到我们Web UI的捆绑包都必须发布一个或多个控制器作为OSGi服务,并确保使用OSGi HTTPService注册自己的servlet和资源(CSS、JSP、图像等)。
注册是通过HTTPService进行的,关键方法是:
httpService.registerResources()
和
httpService.registerServlet()
当Web UI贡献包激活并发布其控制器时,它们会自动被我们的中央Web UI包捕获,并且上述自定义URL映射程序收集这些控制器服务,并保持最新的URL与控制器实例的映射。
然后,当针对某个URL的HTTP请求进来时,它会找到相关的控制器并将请求分派到那里。
控制器完成其业务逻辑并返回应该呈现的任何数据和视图名称(在我们的情况下是JSP)。这个JSP位于控制器的捆绑包中,并且可以由中央Web UI包访问和呈现,正是因为我们使用HTTPService注册了资源位置。我们的中央视图解析器然后将此JSP与我们的中央Sitemesh装饰器合并,并将生成的HTML输出到客户端。
我知道这有点高级,但是如果没有提供完整的实现,就很难完全解释清楚。
我们的关键学习点是看看Bernd Kolb是如何将他的示例JPetstore转换为OSGi,并使用这些信息来设计我们自己的架构。
在我看来,目前对于将OSGi嵌入传统的Java EE应用程序存在过多的炒作和关注,而很少有人考虑真正利用OSGi的惯用语和其优秀的组件模型,以实际允许设计组件化Web应用程序。