本文将快速浏览 Apache 门户项目组的所有项目,并着重介绍门户项目组中的核心项目-Jetspeed-2。
0 评论:
廖 健, 首席实施顾问
2006 年 11 月 02 日
JEE作为建立在Java平台上的企业级应用解决方案,经过这些年不断发展,已经成为企业级开发的工业标准和首选平台。众多厂商如IBM,BEA和Oracle等都围绕该规范推出了相应的,功能强大的产品。JEE规范组中最受业界认同和取得最大成功的就是JEE Web层面规范,发展到今天,已经步入门户(Portal)的时代。
门户,简言之就是提供包括内容聚合、单点登陆、个性化定制和安全管理等服务的基础Web平台。众多JEE产品提供商基于JEE Web层技术推出了自己的Portal产品,著名的产品有IBM WebSphere Portal Server,BEA Weblogic Portal Server等。一直处于技术前沿的著名开源社区Apache,经过这几年的技术积累也形成了自己的门户项目组。该项目组目前已经初具规模,并且拥有了一定的用户群体,经受了一定的市场考验。
本文主要面向有一定JEE编程经验的Java开发者和试图构建自己的门户软件产品的产品经理,因为基于开源项目构建企业级的商用产品,已经在国外取得了许多成功案例。
回页首
名词 | 解释 |
---|---|
Portal | 门户,提供包括内容聚合、单点登陆、个性化定制和安全管理等服务的基础Web平台。 |
Portlet | Portlet是基于web的Java组件。它由Portlet容器管理,能够处理请求,产生动态内容。Portlet被Portal用作为可插拔的用户接口组件,为信息系统提供展现。由Portlet动态产生的内容也被叫做fragment。fragment是遵循某种规则的标记(例如:HTML, XHTML,WML),可与其他的fragment一起建立一个完整的文档。一般一个Portlet产生的内容和其他的Portlet产生的内容聚集在一起形成Portal网页。 |
Portlet Container | Portlet在Portlet容器中运行,Portlet容器为Portlet提供必需的运行环境。Portlet容器包含Portlet(组件)并且管理它们的生命周期,它也为Portlet的参数设置提供持久化的存储。Portlet 容器不是一个类似于 servlet 容器的独立容器。它是在 servlet 容器上通过扩展方式实现的,并重用 servlet容器提供的功能。从Portal的角度来看,Portlet Container是Portal平台所提供的众多服务之一。 |
JSR168,JSR286 | 由于越来越多的公司开发了各自的Portal组件和基于其的Portal产品(如Bea, IBM, Oracle, Sun, Sybase, Novell, SAP, Jetspeed, Vignette 等.这种互不兼容的接口实现不断带给程序提供商各种问题和麻烦, 为了解决这种问题, JCP发布了JSR168 (Java Specification Request), Portlet Specification, 用以提供不同Portal和Portlets之间的互用性。JSR 286是168规范的延伸,是目前最新标准规范,目前仍处在draft状态。 |
SSO Single | Sign-On,即单点登陆。当一个大系统中存在多个子系统时,用户只需要正确登陆其中任何一个子系统,就可以在各个子系统中来回自由切换和使用授予该用户权限的各种资源。一般可以分为两种类型:Web应用之间的单点登陆和门户Web应用和它所连接的后台系统之间的单点登陆。SSO是任何一个门户产品必须解决的问题,必须提供的服务。 |
WSRP | WSRP是OASIS组织的一个规范,它定义了远程门户网站的Web服务。通过Web Service将远程内容抓取到本地,最后通过本地内容聚合引擎展示出来。 |
回页首
在引言中已经列举了Apache门户项目组的组成项目包括:Jetspeed-1/2,Bridges,Pluto,WSRP-4J和Graffito。由于Jetspeed-1和Jetspeed-2角色相同,下文中如果没有特别指出,所有Jetspeed都是指Jetspeed-2。
上图中粉红色包围部分为Apache门户项目,其它由土黄色包围部分为它们的依赖项目。通过上图可以很清楚看到,全部项目都构建在JEE Web Tier上,理论上只要支持Servlet 2.3或以上版本规范的Web容器,都可以作为Apache门户项目的基础平台,但Jetspeed官方其实仅仅声明Tomcat是其唯一支持的Web容器。另一块必要的依赖,是构建在O/R mapping项目Apache OJB之上的数据仓库,用于存放Portal系统信息和用户个性化配置(Profile)。
Portals Bridges项目其本质就是由一组类库构成的轻量级框架,通过该桥接器框架可以在门户上支持众多流行的Web框架,如上图括号中所列举。用户通过它可以很容易的将已有的基于这些流行Web框架的Web应用程序,通过少量的修改和配置,作为Portlet应用程序发布单元发布到Portal上。这个项目不但在Jetspeed上取得的成功,还被众多开源的,甚至商用的门户实现所使用,如JBoss Portal,GridSphere Portal,Stringbeans Portal,Vignette Application Portal,Apache Cocoon Portal和Jetspeed Portal。
Jetspeed项目是整个Apache Portal项目组的核心,它是一个功能完备的,易于扩展的企业级Portal实现,将在下面的文章中着重介绍它。
Pluto是Jetspeed默认的本地Portlet Container实现,它是一个完全符合JSR-168规范的Portlet容器实现,其前身为IBM捐赠的源代码,因此我们至今还能够在WebSphere Portal 5.1.1中看到它的身影。这里要注意本地的意思是指运行在该Portlet容器里的Portlet应用程序在物理上与Portal在同一个JVM进程中。
WSRP-4j是WSRP规范的JAVA实现,目前该项目还处在孵育状态,尚未吸引到足够多的开发者的兴趣。其实,我个人认为这是一个很有前途的技术发展方向,它可以提供类似Html IFrame这样速成的内容抓取能力。Jetspeed已经为WSRP-4j预留了远程Portlet Container的配置选项。
Graffito是用于构建内容管理应用程序的框架,从它自身的架构设计上来看应该是一个独立平台,但事实上该项目复用了大量Jetspeed的模块,并且其表现层为发布到Jetspeed上的几个Portlet应用程序,因此,我在上面的架构图中,将它放在了Jetspeed之上。该项目目前也处在孵育状态下,由于其该项目目前不太活跃,那几个Portlet应用程序都有些小问题。
回页首
标准
体系架构
门户核心特性
门户管理
对Web框架的支持和例子Portlets
用户个性化
门户设计
门户开发工具
应用服务器
本节将从Jetspeed和Spring的关系,运行时架构以及Jetspeed service架构这三方面详细介绍Jetspeed的架构体系。
Jetspeed和Spring
Jetspeed架构体系最大特点,也是其高度可订制的根基就是,它选用著名开源POJO框架Spring作为其底层实现。在项目之初,Jetspeed的开发者们也面临着Spring和PicoContainer的抉择,但事实证明当初的选择是正确的,因为随着Spring不断成长完善,Jetspeed的组件架构也跟着收益良多。从另一个角度来看,Jetspeed也可以作为利用Spring构建自己产品架构的经典范例,值得我们考察和学习。
下图简单描述了目前Jetspeed对Spring的依赖关系:
Beans BeanFactory and the ApplicationContext
Jetspeed主要使用了Spring最核心的IoC引擎BeanFactory和ApplicationContext,管理所有Jetspeed Components的生命周期和依赖关系,所有这些组件的Spring声明全部定义在名为assembly的文件夹中的XML文件里。如果第三方开发者认为默认的Jetspeed组件不足以满足要求,只要按照自己需求编写Jetspeed Component的Interface的实现类,然后修改Spring Bean XML定义,就可以轻易替换掉默认的实现。例如:
default-autowire="no">
class="org.apache.jetspeed.search.lucene.SearchEngineImpl" abstract="false"
singleton="true" lazy-init="default" autowire="default"
dependency-check="default">
${applicationRoot}/WEB-INF/search_index
true
Jetspeed在实现过程中遵循着面向接口编程的最佳实践,上图中的Bean id为org.apache.jetspeed.search.SearchEngine,事实上这是一个定义在核心jetspeed-api组件中的接口,org.apache.jetspeed.search.lucene.SearchEngineImpl为该接口的实现类,这个类定义在components/search组件中,后面的内容就是SearchEngineImpl的构造函数的输入参数,注意最后一个参数org.apache.jetspeed.search.HandlerFactory也是一个Java Interface的接口。Spring在实例化SearchEngine的时候,会首先分析它的构造函数参数是否已经全部满足条件(实例化),Spring会根据搜索bean id为org.apache.jetspeed.search.HandlerFactory的bean,如果已经实例化就直接注入到SearchEngineImpl的构造函数调用里;如果没有就实例化这个bean之后,再注入。
Apache OJB O/R Mappers
由于Spring对Apache OJB提供良好的支持,因此Jetspeed中与数据库相关的功能基本上都用过Spring的PersistenceBrokerDaoSupport实现。这些组件包括:Capablity、DatabasePageManager、PipeLine、Preferences、Profiler、Registry、Security、SSO等。O/R Mapping的信息定义在上面这些组件jar包中的JETSPEED-INF/ojb/%component name%_repository.xml文件中,其中%component name%需要用组建名称替代。
Declarative transaction management
在Jetspeed中,你找不到一行有关于数据库事务的代码,这是因为它采用了Spring的declarative transaction机制,下面一段XML定义了SSOProvider的事物管理:
default-autowire="no">
class="org.apache.jetspeed.sso.impl.PersistenceBrokerSSOProvider"
init-method="init" abstract="false" singleton="true" lazy-init="default"
autowire="default" dependency-check="default">
JETSPEED-INF/ojb/sso_repository.xml
name="ssoProvider" abstract="false" singleton="true" lazy-init="default"
autowire="default" dependency-check="default">
org.apache.jetspeed.sso.SSOProvider
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED PROPAGATION_REQUIRED PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_SUPPORTS
由上图可知,通过Spring 的Declarative Transaction机制,Jetspeed很轻易实现了细颗粒度的事物管理,用户可以很容易配置需要管理事务的方法,如"addSite*"、"updateSite*"和"removeSite"等等,其中"*"为通配符,详细信息见此处。
Spring MVC
由于Jetspeed对Spring的天生依赖,很自然Jetspeed也支持基于Spring MVC framework,详见Jetspeed自带的例子Portlet应用程序。
Jetspeed 组件架构启动过程
看了前面的介绍,你一定想知道Jetspeed是如何将基于Spring的组件架构和标准JEE Web Application架构融合在一起,本节将通过描述Jetspeed Web Application的启动过程来了解融合的细节。首先请看下图:
请点击这里查看Jetspeed Portal启动流程图的大图
由上图可知,Jetspeed Portal从JEE角度来看其实就是一个标准的Web应用程序,只不过在Servlet架构上引入了Component Manager的概念,然后用Spring实现了ComponentManager接口。因此如果你不满意Spring :,更换它也是有可能的。当Servlet被容器停止时,也会同时关闭SpringComponentManager。Servlet启动完毕后,所有通过Spring Bean XML定义POJO都被实例化了,除了那些指定了lazy init属性为true的Bean。
Runtime架构
JetspeedServlet
Jetspeed的运行时大环境是符合Servlet 2.3或以上规范的JEE Web容器,因此大家可以通过观察其web.xml了解或扩展其功能。下面是Jetspeed.war的web.xml:
Jetspeed-2 Enterprise Portal
log4j.config.file
/WEB-INF/conf/Log4j.properties
log4j.config.webApplicationRoot.key
applicationRoot
AJAXFilter
org.apache.jetspeed.ajax.AJAXFilter
AJAXFilter
*.ajax
org.apache.jetspeed.webapp.logging.
Log4JConfigurator
org.apache.jetspeed.engine.JetspeedServlet
jetspeed
org.apache.jetspeed.engine.JetspeedServlet
properties
/WEB-INF/conf/jetspeed.properties
applicationRoot
webContext
1
-
velocity
org.apache.jetspeed.velocity.
JetspeedVelocityViewServlet
org.apache.velocity.toolbox
/WEB-INF/toolbox.xml
org.apache.velocity.properties
/WEB-INF/velocity.properties
org.apache.jetspeed.cache.size
50
org.apache.jetspeed.cache.validation.interval
10000
10
LoginProxyServlet
org.apache.jetspeed.login.LoginProxyServlet
LoginServlet
org.apache.jetspeed.login.LoginServlet
LoginErrorServlet
org.apache.jetspeed.login.LoginErrorServlet
LoginRedirectorServlet
org.apache.jetspeed.login.LoginRedirectorServlet
LogoutServlet
org.apache.jetspeed.login.LogoutServlet
ManagerServlet
org.apache.jetspeed.manager.ManagerServlet
jetspeed
/portal/*
jetspeed
/portlet/*
jetspeed
/jetspeed/*
jetspeed
/fileserver/*
jetspeed
/ajaxapi/*
jetspeed
/desktop/*
jetspeed
/action/*
-
velocity
*.vm
LoginProxyServlet
/login/proxy
LoginServlet
/login/login
LoginErrorServlet
/login/error
LoginRedirectorServlet
/login/redirector
LogoutServlet
/login/logout
ManagerServlet
/manager/*
index.jsp
DB Connection
jdbc/jetspeed
javax.sql.DataSource
Container
Login
/login/redirector
portal-user
Manager