摘要: 我想了解的第一个问题是 Apache Geronimo 为什么首先关注 Apache MyFaces。Tim 解释说它是从 Java™ 2 Platform, Enterprise Edition (J2EE) 1.4 向 Java Platform, Enterprise Edition (Java EE) 5 移植的一部分。“Geronimo 已经是 J2EE 1.4 兼容的应用服务器,但是属于 1.5 规范,需要支持 JSF,而我们提供支持的方法是使用 Apache MyFaces”。在上一期 “Geronimo 叛逆者” 专栏文章中,我想知道 Spring 最重要的功能是什么,当我继续探究下去时,我开玩笑说现在需要有个人来告诉我为什么 JavaServer Faces (JSF) 这样火爆。您不知道,摆在我桌面上的下一件事就是需要 Apache Geronimo 和 Apache MyFaces 之间进行交互,主要集中在其 JSF 的实现。嗯,现在变成一件好事了。我与 IBM® 的 Tim McConnell 进行了一次会谈,他目前正在将 Geronimo 与 MyFaces 集成,我了解到了比预期多得多的关于实际上怎样实现此类规范的内容。
什么是 Apache MyFaces?
我想了解的第一个问题是 Apache Geronimo 为什么首先关注 Apache MyFaces。Tim 解释说它是从 Java™ 2 Platform, Enterprise Edition (J2EE) 1.4 向 Java Platform, Enterprise Edition (Java EE) 5 移植的一部分。“Geronimo 已经是 J2EE 1.4 兼容的应用服务器,但是属于 1.5 规范,需要支持 JSF,而我们提供支持的方法是使用 Apache MyFaces”。
我很好奇。在这里,我们认为有一项技术非常重要,实际上它已添加到了 Java EE 规范中。但它究竟是什么?Tim 告诉我 “JSF 背后的理念就是使您可以更轻松地进行 Web 应用程序开发。它是按照 Model-View-Controller (MVC) 范例建立的模型。它实际上差不多就是该范例的实现。那就是其背后的实际想法。很多没做过 Web 开发的人仍十分熟悉 MVC,因此他们可以快速地更高效地获取并学习 JSF 以及开发 Web 应用程序”。
那听起来很合理,但事情应该不止于此。因此我开始研究 JSF 到底是什么。我发现,为避免使用 JSF 而给自己带来了相当多的麻烦。
如果参与过 Java Web 开发,那么您应该已经了解 JavaServer Page (JSP)。这些是可以将 Java 代码直接嵌入到 HTML 中并且相应地执行的页面。但是更重要的是,JSP 使您可以创建表示 Java 代码的自定义标记。从服务器性能角度来看,这不但更高效,而且具有更高的可维护性,还使非技术人员能够编辑页面。
JSF 将此过程进一步加以推广。它涉及了人们在 Web 编程中常用的元素 —— 主要是表单,还包括预制的组件(那些我曾谈及的自定义标记)来帮助您完成任务。(MyFaces 还包括成百上千个附加组件可以用于添加功能)。例如,考虑清单 1 中所示的 JSF 表单。
清单 1. JSP
<%@ taglib uri=" prefix="h" %><%@ taglib uri=" prefix="f" %>..... <f:view> <h1> <h:outputText value="Login"/> </h1> <h:form id="loginForm"> <h:outputText value="Username: "/> <h:inputText value="#" /> <br /> <h:outputText value="Password: "/> <h:inputText value="#" /> <h:commandButton action="login" value="Log In" /> <h:commandButton action="register" value="Register a new account" /> </h:form> </f:view>.....注意,它混合了标准 HTML 和来自两个标记库的标记,每个标记库指定为作为前缀别名的 URI(代表名称空间)。这些标记包含特定的行为,在这种情况下行为是指输出特定的 HTML。但是请注意,inputText 元素中略有不同。在这里它将引用特定的 Java bean,有可能就如清单 2 中所示的类。
清单 2. Java bean
package com.backstop.renegade;public class UserBean { String username; String password; public String getUsername() { return this.username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return this.Password; } public void setPassword(String password) { this.password = password; }...}
这个 bean 表示表单的数据结构。要将其绑定在一起,可以使用 faces-config.xml 文件(参见清单 3)。
清单 3. faces-config.xml 文件的开源代码
<?xml version="1.0"?><faces-config> <managed-bean> <managed-bean-name>userBean</managed-bean-name> <managed-bean-class>com.backstop.renegade.UserBean</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean></faces-config> 有关如何设置此文件的更多信息的链接,请查看 参考资料,但是现在,注意需要将表单 (userBean) 中使用的对象名链接到类 (com.backstop.renegade.UserBean) 并将范围(scope)指定为引用单个 Web 请求。
但是 JSF 有一项锦上添花的功能。您仍需要提交表单,但是提交到何处?在传统的 HTML 页面中,为每个按钮执行不同的操作相当的麻烦。JSF 通过使用 faces-config.xml 文件中的导航规则 使您可以应对这一问题(参见清单 4)。
清单 4. 向 faces-config.xml 中添加导航规则的开源代码
<?xml version="1.0"?><faces-config> <navigation-rule> <from-view-id>/pages/login.JSP</from-view-id> <navigation-case> <from-outcome>login</from-outcome> <to-view-id>/pages/processlogin.JSP</to-view-id> </navigation-case> <navigation-case> <from-outcome>register</from-outcome> <to-view-id>/pages/registration.JSP</to-view-id> </navigation-case> </navigation-rule> <managed-bean> <managed-bean-name>personBean</managed-bean-name> <managed-bean-class>JSFks.PersonBean</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> </managed-bean></faces-config>
通过这种方法,可以根据由按钮指定的操作所决定的 from-outcome 指定服务器应当从登录页面转至何处。当然,还有其他方法可以触发动作,但是那不在本文讨论的范围之内。
关键是 JSF 极大地简化了 Web 开发。这也是它被列入了 Tim McConnell 的待办事项清单的原因所在。
移至 Java EE(以前称为 J2EE 1.5)
“J2EE 1.4 规范中没有 JSF ,因此这是全新的”,Tim 解释道,“由于这是开源的,没有具体的计划,但是我们希望到下一年 Apache Geronimo 能够兼容 Java EE 5,那就将包括 JSF 1.2 规范。我们正在努力用一种比实现 J2EE 1.4 更有效的方法来实现”。
我始终对 Geronimo 之类的项目的内部工作原理很感兴趣,因此我问 Tim “这一次有什么不同?”
他回答说:“我认为现在 IBM 更多地介入其中,并且不仅是推动其兼容性。很多企业客户都不会用它,除非它是兼容的。” 他指出 Java EE 5 中有很多新规范。“因此还有很多工作要做”。
他先前说过的一些内容引起了我的好奇心。“您说它差不多是一个 Model-View-Controller 模式的实现。为什么是差不多?”
他解释道:“它与 MVC 模式有所不同,因为它是 Web 开发,并且很少有警告和诡辩被添加到规范中。例如,一个有趣之处就在于它们有表单或甚至是 Web 屏幕中的表单元素被更改时触发的事件通知,以便实现程序可以注册以侦听对该字段执行有效更改的事件。因此编程人员可以注册以侦听该字段上的事件,因此他不必查看它是否已被更改,因为如果该字段已被更改,那么他会收到通知。这样做实际上十分明智。对我来说,找到那些由实现而不是由编程人员完成的事件的工作量巨大而又十分复杂;编程人员只需注册该更改中的影响。理念就要使开发更轻松。”
Tim 接着解释了在 Geronimo 中实现 JSF 有什么意义。“有一些内容在服务器上负责规范,例如必须支持的 API。它们必须都来自服务器,而不能来自 Web 应用程序。例如,在 MyFaces 1.1 中,编程人员(开发 Web 应用程序的人员)只需包括 JAR 文件,因此对于 1.2,我们需要忽略那条规范而只需确保它来自 Java EE 5 堆栈。想法是当它与 Java EE 5 兼容时,编程人员无需那样做,因为它将随 Geronimo 提供;它们无需提供 JAR,只需提供应用程序本身。有些代码是我们必须开发以遵循规范的;而有些代码是我们必须开发以启用这些使用 1.2 的应用程序。此外,规范为您提供了一种方法来确定应用程序是否使用 JSF,然后您必须根据该特点执行操作。”
实现规范
所有这一切不禁让我想到:实际实现一些规范是什么样?我的意思是,有一定的规范并遵循规范确实很好,但那是怎样发生的?就像我妻子制作蛋黄酱的那天。所有一切都不是奇迹般地出现,而且一出现就是完成品;必须有人一步步地做出来。(就像将鸡蛋和柠檬原汁混合在一起并制作它们,但您得有想法)。
“我马上就要开始实现 JSR 88 规范,该规范是部署规范”,Tim 告诉我,“这个规范很不错,因为它经过非常精心编写并且易于理解。不是说 JSF 难以理解,而是该规范更多地关注所公开的 API 应有的外观。就像所有其他规范一样。有些规范总会比其他规范更好。”
我问 Tim 是否可以提供更详细一些的信息,并且他还指出软件包定义和描述,我开始意识到这些规范与我们开发人员每天处理的规范没有什么不同。定义 JSF 1.2 的 JSR-252 规范定义了包括的软件包并为必须支持的软件包提供了 XML 模式。规范的文本中定义了每个组件必须执行的操作。
因此除了本质上确凿的内容之外,实现 JSR 规范就像实现任何其他规范一样,因为更改那些内容需要修改整个 Java Community Process,因此这样做肯定比跟老板商谈然后费力地去做要更加复杂。
开源开发与非开源开发的对比
Tim 把使用 Apache Geronimo 称为他 “梦想中的工作”,因此我问他使用开放源码到底有什么特别之处。
“开码开发的特别之处就在于您的贡献实际上就是开发的代码。如果不证明您对 Java 编码或通用编码的精通程度,不贡献代码,则不能成为对 Geronimo 或者我知道的任何其他开放源码有贡献的人。因此在某种意义上,实际上是 ‘代码决定一切’。对于我来说,这有好有坏,但这正是开放源码的发展之路”。
Tim 在严格意义上是 IBM 的软件工程师 —— 与独立使用 Geronimo 相反 —— 因此我问他开源开发与商业开发之间有何区别。“在开放源码 [开发] 中”,他告诉我,“您贡献代码后,社区将审查这段代码,随后所有人都有机会查看、审查这段代码并为您提供反馈。整个过程就是这样。在 IBM 进行产品开发要严格得多,有需要遵循的开发方法,然后还有明晰的阶段:分析、计划、设计、实施、单元测试、功能和系统测试。
“在开放源码 [开发] 中您同样要遵循此过程”,他继续说道,“但是此过程简练得多。没有真正明晰的阶段。在 Geronimo 中,一切都靠社区来推动,但在商业开发中,您的工作通常都根据与产品架构对应的指导信息来执行。在开放源码中,只要代码实现一点社区就会同意通过这段代码,让我们来说,这一点就是兼容 Java EE 5。开放源码的巧妙之处就在于任何人都可以使用所需的内容。同样地,您说 “我将使用 JSF,而且我将遵循 JSR 88 部署规范”。因此发布代码,并获得来自社区的反馈。他们说代码没问题,而您说,“这是我计划编写代码的方法”,然后社区将审查,然后或者同意或者不做任何事情(一种暗示同意)。还有更大的自由度,因为您可以对任何内容进行操作,只要表现出能够对其进行操作的能力并且成为贡献者。因此作为一名开发人员,很明显您要执行单元测试,而审查过程是提交代码的一部分,因为提交后,每个人都可以查看您提交的内容,然后审查并对其进行注释。因此没有清楚的时间表,两个星期后我们将处于此阶段。尤其是对于 IBM 产品开发,它是一种十分严格的方法,该方法十分优秀,因为在我的体会中您得到了质量非常优秀的软件。开源软件的质量也十分出色,它只是一种不同的方法。”
但是 Tim 认为开源开发与商业开发还有一点不同之处:“开放源码还可以带来更多乐趣,真的”。
结束语
Tim 的话使我深思。首先,我的工具库中有了一个新工具:一般情况下用 JSF,特殊情况下用 Apache MyFaces。JSP 我已使用多年;这看似是一种简化应用程序开发的最佳方法。就是导航规则可以简化开发,因此当您能添加本文中未能谈及的所有其他功能时,那么您就是一名真正的赢家!
Tim 还为我提供了一些关于贡献开源项目实战的见解,揭示了实现规范及与社区协作的过程。