JSF的加减法
JSF 本身是很多问题的。当然,JSF不是一项技术,而是标准。看看 javax.faces.* 包里的内容,不是抽象类就是接口,是没有实现的。 JSF 出来的时候目的也不是面向应用开发者的,而是面向组件供应商的,从这点意义上来说,JSF是成功的。Sun提供了一个reference implementation, 但是那更像是教组件供应商如何做组件的一个demo,而非真正意义上的给应用开发人员用的成型的组件。
标准因为要融合各方需求,所以内容只能是各方能力的交集。至于标准之外的东西,则需要各方去发挥。
JSF标准因为是先于成型的应用出来的(不同于EJB3的借鉴hibernate和spring,JSF299的借鉴seam),难免会有预见不足的地方。在某些地方可能作了过分的限制,而另外某些地方则完全没有规定放得太开导致标准实现商完全忽略了它们。
但是 JSF 的初衷是不错的,而且标准本身也足够的可扩展。 所以现在才会诞生如此多的基于 JSF 的框架。 这些框架在不同程度上修复了 JSF 初始制定时的不足。
Ajax4JSF, Facelets, Seam 是这其中三个独立的方向。
1. A4J: 用网络检测工具可以清晰地看到,每次在JSF postback 的时候,虽然可能只有部分页面需要刷新,但整个页面都会被从服务器送往浏览器。这是非常浪费的。 JSF的event-driven模型实际上非常适合部分页面刷新(试想如果没有事件模型,每晃一下鼠标显示器就把整屏幕重画,现在也就没有 windows了),但是因为ajax出来的时候JSF标准已经final了,就没有把Ajax考虑进去。对于事件模型来说,把整屏幕重画改为部分组件重画是件相对容易的事情,这也就是 Ajax4JSF 这个项目的目的。是否开启AJAX,可以不需要javascript,只是更改页面中的某个开关(tag)就行了。
2. Facelets: JSF是建立在JSP上的,但这是完全没有必要的。JSP不是模板语言,它只是简单得把嵌入在html里的java语言原样放入Java的源文件里,实际上是混合的html和java。这种模型和JSF的事件模型没有任何互补的关系。相反,它给JSF加入了不必要的限制。Facelets的目的在于取代 jsp在JSF里的地位。它是真正的模板语言,el表达式可以嵌入在页面的任何位置,比如写成:
<h2>Hi,I'm Jordan, I think the winner of this cup is #{winner.name}, is that right?</h2>
Facelets不需要编译,页面是hot-deploy的,性能比jsp快。另外,facelets本身提供了加参模板的功能,定制新的组件可以完全不写java,只把页面里的需要提成组件的内容扔进分离的页面,并且在taglib.xml里面加入tag指向分离的页面,并指定参数名字就可以了。 JSF最为人诟病的组件缺乏的问题,在facelets这里得到了缓解,实际上是不怎么需要第三方组件就可以快速写出舒服的代码来。Facelets还有其它的功能,比如debug页面显示facelets页面出错的行号,比如无限嵌套的模板,等等。
3. Seam: Seam 其实本身是无关JSF的,但是因为它从一开始就建在JSF上面,所以也不得不对JSF的一些问题进行修复。
Seam的工作需要分开来细说:
◆page行为
◆Context-filter
◆RESTful(重建页面参数)
◆异常处理
◆跨越重定向的状态
现在我们有了JSF的加减法:
JSF - (全页面刷新) + Ajax4JSF - Jsp + Facelets + 全局Page行为 + Context-filter + Restful参数绑定 + 可定制异常 + 跨越重定向的状态 = “ -_- !一大碗炸酱面”
就好像一件黄金圣衣,经过无数次修补,虽然还能再用,但是实在不如重铸了。
JSF 需要一套整合的模型,使这些各个分散的部分重新以一种整体的局面展现出来。它需要把多余的东西抛弃掉,把新的内容以更集成的方式融在一起,因为光是熟悉这些不同分散的部分,理解它们之间的关系,知道哪里会有BUG,哪里则可以避免这些BUG,并且在运用的时候总是用对该用的东西,这已经使人非常头大了。 JSF作为标准来说是成功的,在这一标准下有了如此多的可以插拔的第三方软件。但是该是时候对这些零散的东西统一了。就好像ubuntu在统一的指导思想下集合了尽可能多的零散的开源软件,使它们可以被一种简单并且相似的方式获取,使我不需要像在Gentoo里安装任何一个东西都要搜索搜索再搜索,了解它的来源,了解它的BUG,了解我的硬件是否支持。作为用户,我不想学习,我想有明白的人替我作决定,那是***的,特别是当这些决定make sense的时候。
现在的Seam正是朝这个方向走的。能走这样的路,得有两个条件,一是有众多零散的可用的东西,但是它们缺乏统一的形式(但它们得有能够统一的背景,比如 ubuntu下是posix标准,Seam下是JSF标准);二是有对该领域非常熟悉的人来做这样的事情。上面提到的Seam对JSF的改进其实只是 Seam框架下非常小的一部分,是Seam在向这个目标前进的必须的一个步骤,是在Seam内核基础上水到渠成的东西,而远非Seam的全部。正如 Seam的名字所示:缝合;正如ubuntu的名字所示:分享与同在。它们的制定者在决定之初即是向着这一目标前进的。
已经early draft review的JSR 299, 即是借鉴了Seam(以及其它比如Guice)的一个标准,试图把这一方向推得更远。
至于对于缝合所需要的本事,Seam的conversation模型,CoC理念,元注解配置+xml补充方式,动态双向注入模型(不同于spring的静态单向注入),扩展了的EL等,是其基础。内部事件和监听模型,和drools的安全集成模型,和hibernate-seach, hibernate-validation, seam-remoting, jbpm,groovy,itext的集成,是其在基础之上的应用。这些则需要另外的文章来写了。
不说Seam诞生的大环境和Seam产生的语言基础,只是说Seam本身的功能,大概也可以,不过我认为非常多的外在功能都只是某些环境外在因素和基本内在因素所决定了的。大环境和内在可能定了之后,细节的东西只是做就可以了。所以没有办法,还是得绕开Seam本身说些题外话。
JSF的加减法说了一下 Seam诞生的环境,这是外在机会,是融合各种技术的可能性,是广的纬度。 这篇文章说说java上的可能性,是何让Seam具有了融合的本事,是内在能力,从深的纬度上说吧。
【编辑推荐】