AJax技术

JSF 2 简介,第 3 部分: 事件处理、JavaScript 和 Ajax

字号+ 作者:H5之家 来源:H5之家 2016-07-20 10:02 我要评论( )

JavaServer Faces (JSF) 2 专家组成员 David Geary 将在这一期文章中结束这部有关 JSF 2 新特性的系列文章(共 3 部分)。本文介绍如何使用该框架的新事件模型和

JSF 的最大卖点在于它是一种基于组件的框架。这意味着您可以实现供其他人重用的组件。这种强大的重用机制在 JSF 1 中基本上是不可能实现的,因为在 JSF 1 中实现组件是非常困难的事情。

然而,正如 第 2 部分 所述,JSF 2 通过一种名为复合组件 的新特性简化了组件的实现 — 无需 Java 代码和配置。这一特性可以说是 JSF 2 中最重要的部分,因为它真正实现了 JSF 组件的潜力。

在这份有关 JSF 2 的第三篇也是最后一篇文章中,我将展示如何利用新的 Ajax 和事件处理功能(也在 JSF 2 中引入)构建复合组件特性,要从 JSF 2 中获得最大收益,需要遵循下面的技巧:

对于第一个技巧,我将简要回顾已在 第 2 部分 中详细描述过的两个组件。对于后面的技巧,我将展示如何使用 Ajax 和事件处理功能来改造这些组件。

技巧 1:组件化

我在 第 1 部分 中引入的 places 应用程序包含有大量复合组件。其中之一便是 map 组件,它显示一个地址地图,其中包含一个缩放级别下拉菜单,如图 1 所示:

图 1. places 应用程序的 map 组件

map 组件

清单 1 显示了经过删减的 map 组件列表:

清单 1. map 组件

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" <html xmlns="http://www.w3.org/1999/xhtml" ... xmlns:composite="http://java.sun.com/jsf/composite" xmlns:places="http://java.sun.com/jsf/composite/components/places"> <!-- INTERFACE --> <composite:interface> <composite:attribute/> </composite:interface> <!-- IMPLEMENTATION --> <composite:implementation"> <div> ... <h:panelGrid...> <h:panelGrid...> <h:selectOneMenu onchange="submit()" value="#{cc.parent.attrs.location.zoomIndex}" valueChangeListener="#{cc.parent.attrs.location.zoomChanged}"> <f:selectItems value="#{places.zoomLevelItems}"/> </h:selectOneMenu> </h:panelGrid> </h:panelGrid> <h:graphicImage url="#{cc.parent.attrs.location.mapUrl}"/> ... </div> ... </composite:implementation> </html>

组件的一大优点就是可以使用更有效的替代方法替换它们,同时不会影响到相关的功能。比如,在图 2 中,我使用一个 Google Maps 组件替换了 中的 image 组件,Google Maps 组件由 GMaps4JSF 提供(见 ):

图 2. GMaps4JSF 的 map 图像

GMaps4JSF map 组件

map 组件的更新后的代码(进行了删减)如清单 2 所示:

清单 2. 使用一个 GMaps4JSF 组件替换 map 图形

<h:selectOneMenu onchange="submit()"value="#{cc.parent.attrs.location.zoomIndex}" valueChangeListener="#{cc.parent.attrs.location.zoomChanged}"> <f:selectItems value="#{places.zoomLevelItems}"/> </h:selectOneMenu> ... <m:map address="#{cc.parent.attrs.location.streetAddress}, ..." zoom="#{cc.parent.attrs.location.zoomIndex}" renderOnWindowLoad="false"> <m:mapControl position="G_ANCHOR_TOP_RIGHT"/> <m:mapControl/> <m:marker/> </m:map>

要使用 GMaps4JSF 组件,我从 GMaps4JSF 组件集合中使用 <m:map> 标记替换了 <h:graphicImage> 标记。将 GMaps4JSF 组件与缩放下拉菜单连接起来也很简单,只需为 <m:map> 标记的 zoom 属性指定正确的 backing-bean 属性。

关于缩放级别需要注意一点,那就是当一名用户修改缩放级别时,我将通过 <h:selectOneMenu> 的 onchange 属性强制执行表单提交,如 中第一处使用粗体显示的代码行所示。这个表单提交将触发 JSF 生命周期,这实际上将把新的缩放级别推入到保存在父复合组件中的 location bean 的 zoomIndex 属性中。这个 bean 属性被绑定到输入组件,如 中的第一行所示。

由于我没有为与缩放级别修改相关的表单提交指定任何导航,JSF 在处理请求后刷新了同一页面,重新绘制地图以反映新的缩放级别。然而,页面刷新还重新绘制了整个页面,即使只修改了地图图像。在 中,我将展示如何使用 Ajax,只对图像部分重新绘制,以响应缩放级别的修改。

login 组件

places 应用程序中使用的另一个组件是 login 组件。图 3 展示了这个 login 组件的实际使用:

图 3. login 组件

login 组件

展示了创建 所示的 login 组件的标记:

清单 3. 最基础的 login:只包含必需的属性

<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:util="http://java.sun.com/jsf/composite/components/util"> <util:login loginAction="#{user.login}" managedBean="#{user}"/> </ui:composition>

login 组件只包含两个必需的属性:

  • loginAction:登录 action 方法
  • managedBean:包含名称和密码属性的托管
  • 中指定的托管 bean 如清单 4 所示:

    清单 4. User.groovy

    package com.clarity import javax.faces.context.FacesContext import javax.faces.bean.ManagedBean import javax.faces.bean.SessionScoped @ManagedBean() @SessionScoped public class User { private final String VALID_NAME = "Hiro" private final String VALID_PASSWORD = "jsf" private String name, password; public String getName() { name } public void setName(String newValue) { name = newValue } public String getPassword() { return password } public void setPassword(String newValue) { password = newValue } public String login() { "/views/places" } public String logout() { name = password = nameError = null "/views/login" } }

     

    1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

    相关文章
    网友点评