页面动作来帮忙
Seam 的页面动作可以帮助您预先拦截呈现的假信号。页面动作是使用方法绑定指定的,方法绑定在进入页面时、Render Response 阶段之前执行。对于 /WEB-INF/pages.xml 配置文件中一个给定的视图 ID,可以配置任意数量的方法绑定。(或者,可以通过将它们放在视图模板邻近的一个文件中,复制它的名称,但是将文件扩展名换为 *.page.xml,从而分解每个页面的定义)。对于页面动作,XML 是有必要的,因为视图 ID 非常容易变化。就像 JSF 通过 Apply Request Values 阶段的值绑定将 post 数据映射到模型对象一样, Seam 可以通过执行页面动作之前的值绑定将任意请求参数映射到模型对象。这些请求参数注入的配置嵌套在页面动作 XML 声明中。如果页面动作方法调用返回一个非空字符串值,则 Seam 将其当作一个导航事件。因此,不必迁移到一个完整的基于动作的框架中,仍然可以比得上最特别的特性。Seam 包括很多内置的页面动作,它们通常跨应用程序使用。其中包括用于验证 conversation 是否建立的一个动作;可以启动、嵌套和结束 conversation 的动作;处理预期异常的动作;以及确保适当的凭证的动作。
页面动作是启用对 JSF 的书签支持的关键。Seam 的创立者允许在进入页面时请求参数 actionMethod 触发一个方法调用,从而利用了这一特性。更妙的是,您不需要做任何额外的工作就能为书签创建链接。 Seam 提供了两个组件标记:s:link 和 s:button,用以处理细节。这两个标记分别对应于 JSF 中的 h:commandLink 和 h:commandButton。不同之处在于,Seam 组件标记组装的链接使用一个 HTTP GET 操作发出请求,而不是使用 JSF 的 HTTP POST 表单提交模型表示。因此,Seam 创建的链接对书签更 “友好”,对于开发人员来说更方便。
您可能还注意到,当使用页面动作时,地址栏中的 URL 对应于正在显示的页面,而不总是背后的一个页面。(后一种情况之所以会发生,是因为 JSF 将表单配置为 post 回生成它们的 URL。地址栏没有更新,以反映执行动作后的新视图,因为 JSF 通过一个服务器端重定向使之前进。)如果您想演示页面动作的灵活性,那么可以使用它们来创建 RESTful URL(例如 /faces/product/show/10)。为此,将页面动作方法映射到视图 ID“/product/show/*”,其中 /faces 前缀是 JSF servlet 映射部分。然后,该页面动作方法利用请求 URL,以判断数据类型和数据标识符,加载数据,然后导航到适当的模板。这个例子很明显地演示了 JSF 请求 URL 与视图模板之间并不一定存在一对一的关系。
工厂组件
JSF 最大的一个失败是没有在用户触发的动作或动作监听器方法以外的其他地方提供可靠的机会来为视图准备数据。将逻辑放在一个动作方法中并不能保证该逻辑在视图呈现之前得到执行,因为页面视图并不总是在用户触发的事件之后。
例如,当一个 JSF 应用程序的 URL 第一次被请求时,会发生什么情况?如果需要在该页面上显示从服务层获得的一组数据,那么在 JSF 生命周期中始终没有好的机会来取数据。您可能会认为,可以将逻辑放在映射到视图中值绑定表达式的 backing bean 的 getter 方法中。但是,每当 JSF 解析那个表达式时,就会触发另一个调用,新的调用又会访问服务层。即使页面上只有少数几个组件,getter 方法也可能被推后数次执行。显然,就性能而言这不是最优的。即使通过使用受管 bean 上的私有属性维护状态,每当面对那样的情况时,仍然必须增加额外的管道。一种解决方案是使用 Seam 的页面动作。但是由于这种任务是如此常见,Seam 提供了一个更加容易的解决方案。
Seam 引入了工厂数据提供者(factory data provider)的概念,工厂数据提供者由 @Factory Java 5 注释指定。虽然有两种方法配置工厂,但是最终结果是同样的数据只需在第一次被请求时准备一次。 Seam 确保随后对相同数据的请求将直接返回之前创建的结果集,而不必再一次触发对查找方法的调用。通过与 conversation 相结合,工厂数据提供者成为实现数据短期缓存的非常强大的特性,否则,取这些数据的代价可能较高。在 JSF 不负责减少它解析一个值绑定表达式的次数的情况下,Seam 的工厂特性常常变得非常方便。
有状态 conversation
关于 JSF 很容易引起困惑的一个地方是它的状态管理功能。JSF 规范解释了在接收一个动作之后页面是如何 “恢复(restored)” 的,在此期间时间事件要进行排队,选择要注册。仔细研究规范中的用词可以发现,虽然在 postback 上恢复了组件树,但是那些组件使用的 backing bean 数据并没有被恢复。组件只是以字符串文字的形式存储值绑定(使用 #{value} 语法的 EL 表达式),只在运行时解析底层数据。这意味着如果一个值是短期作用域存储的,例如页面或请求作用域,那么当 JSF 生命周期到达 Restore View 阶段时,这个值将消失。
不将值绑定数据存储在组件树中的一个最值得注意的不利方面是虚幻事件效果(见 参考资料),这是由 UIData 家族中的临时父组件导致的。如果一个值绑定表达式引用的模型数据不再可用,或者在组件树被恢复之前发生了更改,那么组件树的一些部分将被撤销。如果在这些被撤销的分支中,有一个组件中触发了一个事件,那么它将不能被发现,而且这种事件丢失情况是难于觉察的。(只是队列开发人员可能会惊呼 “为什么我的动作没有被调用?”)
虽然丢失的事件看上去像是异常状况,但并不会导致 JSF 生命周期中出现红色标志。因为这些组件依赖底层数据,以保持稳定和适当地被恢复,所以 JSF 难于知道丢失了什么。
不幸的是,JSF 规范天真地引导开发人员将大多数 backing bean 放入 conversation 作用域中 —— 甚至可以在 “方便的” 作用域内调用它。然后,服务器管理员则必须处理由此导致的 “内存溢出” 错误,集群环境中的服务器相似性,以及服务器重启时的串行化异常。MyFaces Tomahawk 项目通过 t:saveState 标记的形式提供了对虚幻事件的一个解决方案。MyFaces 标记允许将数据(包括整个 backing bean)存储为组件树的一部分,而仅仅是值绑定。然而,这种解决方案有些简陋,很像使用隐藏的表单字段在请求之间传递值。它还造成视图与控制器之间紧密耦合。Seam 的创立者意识到,Java Servlet 规范中三个内置的上下文(请求、会话和应用程序)不足以构成数据驱动的 Web 应用程序的全部作用域。在 Seam 中,他们引入了 conversation 作用域,这是一个有状态作用域,由页面流的起止点界定。
Seam 的 conversation 作用域
“Seam 强调使用有状态组件。” Seam 参考文档中的这句话体现了 Seam 的核心思想。很长一段时间内,关于 Web 应用程序的看法是,它们是无状态的 —— 这种思想一定程度上要归因于 HTTP 协议的无状态性质。大多数框架为了迎合这一点,在结束页面呈现之前提供 one-shot-processing。这种方法导致很大的阻力,因为任何大的应用程序都需要长时间运行的 conversation 来满足某些用例。需要有状态上下文的应用程序的例子有很多,例如存储检查过程、产品定制、多页表单向导和很多其他基于线形交互的应用程序。虽然其中有些例子可以通过使用 URL 参数(aka RESTful URL)和隐藏字段在页面之间迁移数据,但是这样做对于开发人员来说有些繁杂。而且,如今这种做法已经过时了。因为大多数 Web 框架仍然在无状态模型下操作,所以您常常发现自己走出了这种框架,而 “开辟” 出定制解决方案。
JSF 大量依赖于 HTTP 会话,试图引入有状态上下文。实际上,当和会话作用域的 backing bean 一起使用时,JSF 组件的行为要好得多。如果不小心设计,过度使用 HTTP 会话会导致严重的内存泄漏、性能瓶颈和安全问题。此外,在多标签浏览器环境中,使用 HTTP 会话可能导致非常奇怪的行为,破坏用户神圣的 Back 按钮。值得注意的是,JSF 只是与您互作让步:它是一个有状态 UI,处理保存和恢复组件树的所有细节,但是它在保存和恢复数据方面没有提供帮助。因此,JSF 带来有状态 UI,而您则带来有状态数据。不幸的是,需要由您来负责确保它们是相符的。
在 Seam 之前,使用有状态数据的惟一方便的方式是依赖于 HTTP 会话。Seam 纠正了这个问题,它通过建立一个全新的 conversation 作用域,完善了 JSF 的状态管理。随着将 Seam 添加到 JSF 生命周期中,conversation 上下文与一个浏览器窗口(或标签页)联系在一起,这个浏览器窗口(或标签页)由随每个请求提交的一个标志来标识。conversation 作用域使用 HTTP 会话的一个单独的区段在页面之间迁移数据。记住,Seam 使用 HTTP 会话用于 conversation 持久性这一点是完全透明的。 Seam 并不是不负责任地将组件推卸到 HTTP 会话中,使其茫然地呆在那里。相反,Seam 小心地管理那个区段的会话数据的生命周期,并且当 conversation 终止时,自动清除它们。Seam 聪明地使用双射来允许以一种新的说明性方式使数据流入和流出一个 “Web conversation” 的每个页面。 Seam 的 conversation 作用域同时还克服了 HTTP 会话的限制,帮助开发人员放弃使用 HTTP 会话。
异常处理
Seam 的创立者曾说过:“在异常处理方面,JSF 非常有限”。这一点显然毫无争议。 JSF 规范完全忽视异常管理,将责任完全放在 servlet 容器上。允许 servlet 容器处理异常的问题在于,这严重限制了错误页面上显示的内容,并且禁止了事务回滚。由于错误页面是在请求分发器转发之后显示的,FacesContext 不再在作用域中,因此这时执行业务逻辑就太迟了。您的最后一线希望是使用 Servlet API,并抓住 javax.servlet.error.* 请求属性,以搜索能表明出错处的信息。
这一点上,Seam 再次扮演救世主,它提供了优雅的、说明性方式的异常处理。异常管理可以通过注释指定,或者在配置文件中指定。可以将注释 @HttpError、@Redirect 和 @ApplicationException 放在异常类的上面,表明当异常被抛出时应该采取的动作。对于那些不能修改的异常类,可以使用 XML 配置选项。Seam 中的异常管理器负责发送 HTTP 状态码、执行重定向、促使页面呈现、终止 conversation 和定制出现异常时的用户消息。由于在开始呈现响应之后,JSF 不能改变动作的过程,一些固有的限制规定了何时才能处理这些异常。通过适当使用其他 Seam 特性,例如页面动作,可以确保大多数异常情况在呈现响应之前得到解决。
Ajax remoting
由于最后发行的 JSF 规范几乎与 Ajax 重合,JSF 框架在异步 JavaScript 和局部页面呈现(partial page rendering)方面帮助不大。在某些时候,甚至这两种类型的编程甚至不一致。最终的解决办法是建议使用 JSF PhaseListener 或组件 Renderer 来处理局部页面更新。即使如此,这一点仍然很明显:JSF 使得 Ajax 比过去更难于采用。有些项目,例如 ICEfaces,甚至用一个更好的、专为页面-服务器通信设计的技术(即 direct-to-DOM rendering)来替代 JSF 生命周期。
Seam 为 JavaScript remoting(常常记在 Ajax 名下的一种技术)提供了一种独特的方式,该方式与 Direct Web Remoting (DWR) 库的方式大致相似。Seam 通过允许 JavaScript 直接调用服务器组件上的方法,将客户机与服务器连在一起。Seam remoting 比 DWR 更强大,因为它可以访问丰富的上下文组件模型,而不仅仅是一个孤立的端点。这种交互构建在 JSF 的事件驱动设计的基础上,所以它可以更严格地遵从 Swing 范例。最妙的是,提供这个功能的同时并没有增加开发方面的负担。只需在组件的方法上加一个简单的注释 @WebRemote,JavaScript 就可以访问该方法。当服务器组件的状态被修改之后,Ajax4JSF 组件库就可以处理局部呈现。简言之:Seam remoting 库使 JSF 可以实现它的创立者一向期望的交互设计。
结束语
根据您目前在 无缝集成 JSF 系列 中了解到的内容,可以毫不牵强地说在使用 JSF 的开发中不使用 Seam 是反常的。作为进一步的证明,只需看看 JSR 299, Web Beans 的投票结果(见 参考资料)。显然,在不久的将来,Seam 会成为一个官方规范,Java EE 栈最终将提供 “显著简化的基于 Web 的应用程序编程模型”。这对 JSF 开发人员和 Seam 来说是一个好消息。但是,即使没有声明要成为一个 Java 标准,Seam 也是 JSF 的一个有价值的补充。
Seam 只需很少的设置就可以开始用于 JSF —— 而正是这一点小小的付出,就能解决 JSF 开发中的一些最麻烦的难题。回报胜于付出 —— 这里讨论的 Seam 的优点还只是一个开始。
分享到:
相关推荐
为 JSF 量身定做的应用程序框架,JavaServer Faces (JSF) 是用于 Java™ Web 应用程序的第一个标准化的用户界面框架。而 Seam 是一个扩展 JSF 的强大的应用程序框架。在这个由三部分组成的新系列中的第一篇文章中,...
JavaServer Faces (JSF) 是一个用于构建Web应用程序的Java EE组件模型和渲染框架。它为开发者提供了丰富的UI组件、事件处理机制和生命周期管理,使得创建用户界面变得更加简单。在这个项目中,JSF将与三大框架——...
在IT行业中,开发Web应用程序是常见的任务之一,而JavaServer Faces (JSF) 是一个用于构建用户界面的Java EE框架,常用于创建企业级的Web应用。NetBeans是一款功能强大的集成开发环境(IDE),它支持多种编程语言,...
在本示例程序中,JSF框架与其他技术如Hibernate、Spring和EHCache一起使用,构建了一个完整的后端驱动的应用程序。 首先,JSF框架的核心组件包括Facelets(用于创建用户界面的模板技术)、UI组件库(如PrimeFaces或...
JavaServer Faces(JSF)是一种Java平台上的Web应用程序框架,特别设计用于构建用户界面。它遵循Model-View-Controller(MVC)架构模式,将表示层(View)、业务逻辑(Model)和控制流程(Controller)分离开来,...
3. **集成支持**:除了基本的JSF功能外,WebSphere Studio 还支持与其他J2EE组件(如EJB、Web Services等)的集成,这为创建复杂的企业级应用程序提供了强大的支持。 #### 三、创建JSF Web项目 根据提供的部分内容...
JavaScript Server Faces(JSF)是一种Java技术,用于构建企业级的Web应用程序。它是一个MVC(Model-View-Controller)框架,旨在简化用户界面组件的创建、管理以及与后端服务器的数据交互。JSF提供了丰富的组件库,...
JSF(JavaServer Faces)是Java平台上用于构建用户界面的组件模型框架,它提供了一种声明式的方式来创建和管理Web应用程序的用户界面。这个压缩包文件"myfaces-example-simple-1.1.7-SNAPSHOT"包含了一个JSF的实际...
JavaServer Faces(简称JSF)是Java平台上的一个标准Web应用程序框架,由Java Community Process(JCP)定义为Web应用程序开发的标准模型。JSF提供了丰富的功能来帮助开发者构建企业级的应用程序,其中包含了多种...
JSF是一个为开发人员提供这些用户交互的 UI框架,它可以大大简化交互式 Web 应用程序的开发。JSF 提供的 UI 框架由 UI组件和运行时组成,运行时负责把这些组件呈现给客户端并管理页面的生命周期(错误、验证器、导航...
JavaServer Faces (简称JSF) 是一个基于Java EE标准的Web应用程序框架,旨在简化Web应用程序的开发过程。JSF的目标是提供一套标准化的方法来构建和管理用户界面。它不仅提供了一个标准的编程接口,还配备了一套丰富...
JSF是一种用于构建Java Web 应用程序的标准框架(是Java Community Process 规定的JSR-127标准)。JSF(Java Server Faces)技术为开发基于网络用户界面的Java开发者提供了标准的编程接口API以及标签库。就像Struts框架...
在JSF和Facelets结合的应用程序中,开发者通常会遵循以下步骤: 1. **定义组件**: 使用Facelets的XML语法(通常以`.xhtml`为扩展名)创建页面,这些页面可以包含JSF组件(如`<h:inputText>`,`<h:commandButton>`等...
JavaScript Faces (JSF) 是Java平台上的一种用于构建用户界面的模型-视图-控制器(MVC)框架,专为创建企业级Web应用程序而设计。这个"一个jsf企业级程序示例"旨在向开发者展示如何有效地利用JSF来构建高效、可维护...
通过这个例子,我们可以看到JSF如何将复杂的Web应用程序分解为易于管理和维护的组件,并通过其强大的框架特性简化开发过程。JSF的这些优势使其成为应对现代应用程序开发挑战的重要工具,特别是在需要快速构建和扩展...
**JSF(JavaServer Faces)** 是一种Java技术,用于构建Web应用程序的用户界面。它是一种组件化的MVC(Model-View-Controller)框架,允许开发者通过声明式的方式创建交互式的用户界面。在JSF中,视图由HTML或其他...
JSF,全称为JavaServer Faces,是Java EE平台上的一个MVC(Model-View-Controller)框架,用于构建用户界面,尤其适用于企业级Web应用程序的开发。它提供了一种声明式的方式来创建用户界面,并与后端业务逻辑进行...
**JSF(JavaServer Faces)**是Java平台上用于构建用户界面的一种Web开发框架,它提供了一种组件化和事件驱动的方式来构建交互式的Web应用程序。JSF的核心在于它将UI组件与后端业务逻辑分离,使得开发者可以专注于...
**JSF(JavaServer Faces)** 是一种Java技术,用于构建Web应用程序的用户界面。它提供了组件模型和事件处理机制,使得开发人员可以更轻松地创建动态、交互式的Web页面。JSF的核心概念包括组件、事件、应用上下文和...
### 在NetBeans环境下使用JSF+Tomahawk框架开发J2EE程序的知识点解析 #### 一、基础知识介绍 **1.1 J2EE技术概述** J2EE(Java 2 Platform, Enterprise Edition)是一种广泛使用的Java平台标准,用于开发企业级...