JSF 2.0阅读笔记:事件(一)_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > JSF 2.0阅读笔记:事件(一)

JSF 2.0阅读笔记:事件(一)

 2011/1/7 8:29:44  kidneyball  http://kidneyball.javaeye.com  我要评论(0)
  • 摘要:一、什么是事件什么是事件?简单来说,就是一些由当前程序关注范围之外的原因发起的一些行为(action),而你在程序内部需要对这些行为作出响应和处理。利用事件,能够有效地缩小程序片段所需要关注的范围,也就是减少了程序员在开发当前程序片段时的关注点,实现传说中的高聚合和松耦合。一个事件体系中包含了两个部分,事件的发起方和事件的监听方(处理方)。在开发事件发起方时,可以完全不知道事件监听方的任何细节,而只需要针对事件体系本身定义五个要素:事件的类型、监听方的注册方式、事件触发时现场信息的传递方式
  • 标签:事件 笔记
一、什么是事件

什么是事件?简单来说,就是一些由当前程序关注范围之外的原因发起的一些行为(action),而你在程序内部需要对这些行为作出响应和处理。利用事件,能够有效地缩小程序片段所需要关注的范围,也就是减少了程序员在开发当前程序片段时的关注点,实现传说中的高聚合和松耦合。一个事件体系中包含了两个部分,事件的发起方事件的监听(处理方)。在开发事件发起方时,可以完全不知道事件监听方的任何细节,而只需要针对事件体系本身定义五个要素:事件的类型、监听方的注册方式、事件触发时现场信息的传递方式、事件的触发和广播时机、监听器返回处理结果的方式。在开发监听方时,必须清楚以上五个要素,在正确的事件类型上注册监听器,根据现场信息进行恰当的处理,最终向事件发起方提供处理结果,以影响事件发起方的后续处理。换句话说,事件体系为事件的发起方和监听方规定了一种标准化的沟通方式,避免了它们之间互相直接依赖对方的实现细节。

在考察一个事件模型时,我们通常也是从这五个要素着手的:

1. 事件的类型。概念上来看,事件的类型就是事件的名称,它通常反映了事件触发的时机。例如说,组件上的onclick事件表明了这个事件会在组件被点击时触发。触发事件的主体(例如Button组件),称为事件源。一个事件源有可能触发多种事件,同一种事件也由可能被多个事件源所触发,但对于一个具体的事件,其事件源只有一个。

2. 监听方的注册方式。为了建立起事件发起方与监听方的关联,事件发起方需要提供一种或多种方式,让监听方注册监听(回调)方法,当事件触发时,事件发起方依次调用已注册的监听方法,通知监听方进行处理。在Java中回调方法必须包装为监听接口的实现类,通常命名为为监听器(Listener)。一个事件上往往可以注册多个监听器,事件触发时这些监听器会被依次通知,因此这种依次触发多个监听器的行为也称为事件的广播(broadcasting)。

3. 事件触发时现场信息的传递方式。在编写监听器逻辑时,往往需要知道触发事件时在事件发起方的一些上下文信息。有时,监听方能直接获取到发起方的当前上下文信息,因此无需发起方作特别的处理。但大多数情况下,为了方便编写监听器代码,或者应付监听方无法获取到发起方当前上下文的场景,通常会由发起方在触发事件时收集与事件相关的上下文信息,以某种方式传递给事件监听方。这种事件现场信息的传递,通过回调方法上的参数传递方式进行。为了对发起方和监听方的接口依赖进一步解耦,我们往往会对事件现场信息进行抽象,封装为事件类(Event Class)。事件类(携带事件的现场信息)与事件的类型(反映事件触发时机的名称)往往是一一对应的,因此在许多事件编程模型中,会使用事件类来标识对应的事件类型。但应该明确其中的区别,事件的类型是概念上的东西,它的标识方式可以是事件类,也可以是字符串,或者数字。而事件类的实例则是实实在在的事件现场信息。

4.事件的触发和广播时机。一些简单的事件机制,会在事件触发时立刻创建出事件类实例,然后直接调用监听器的回调方法来广播事件,这种情况我们可以认为事件的触发与广播的时机是一致的。对于一些复杂的场景,例如事件发起方与监听方的处理需要异步或延时进行的时候,就需要引入事件的排队机制。在事件触发时,只是将事件类实例加入队列,在合适的时机再依次广播。

5. 监听器返回处理结果的方式。灵活的事件发起方允许监听方在处理完毕后,向其返回一些信息,以影响事件发起方的后续处理流程。监听器返回处理结果的方式通常有两种,一是修改某些由双方共享的上下文信息(例如在监听方法中调用FacesContext.responseComplete()通知JSF引擎跳过后续处理),二是通过回调方法的返回值(例如在action方法中返回字符串通知JSF引擎导航到另一页面)。具体的方式和语义,是由事件发起方来定义的。

对于UI控件的事件机制,我们还会关注事件广播时多个针对该事件的监听器的处理顺序。但对于没有明确父子嵌套关系的监听器体系(例如JSF中),我们通常不关心,也无法精确地确定同一个事件的多个监听器的执行顺序。因此这不在本文讨论的范围。

下面,就以这五要素为主线,来看看JSF2.0中的事件体系。

二、JSF2.0中的事件

在JSF1.2中,已经提供了两类事件,FacesEvent(重复一下,FacesEvent是事件类,其实例将携带某次具体事件的现场信息,在这里则用来标识一种事件类型)PhaseEvent。在JSF2.0中,又再加入了一类新的事件,SystemEvent

在JSF2.0的规范文档(JSR314)的Sec3.4.1中,给出了事件模型的API总图,如下:

事件类静态类图



监听器类静态类图

DBAC537227ED47.png" />

2.1 FacesEvent

FacesEvent这个术语不太好翻译,鉴于FacesContext可以理解为JSF的应用上下文,而且FacesEvent的两个主要子类:ActionEvent与ValueChangeEvent都是在InvokeApplication阶段触发的,我们也可以把FacesEvent理解为JSF的应用事件。事实上,在JSF2.0规范中,关于FacesEvent的章节(Sec3.4.2)标题就是《Application Events》.

FacesEvent是JSF组件体系的一个重要组成部分,它是一类由组件发起的事件。我们知道,面向组件开发的一个重要特征就是把UI分离为展现与行为两部分,其中UI行为就以组件事件的方式来体现。具体到JSF中,就是FacesEvent。在JSF中,FacesEvent抽象类和相关的处理逻辑构成了组件事件的整体框架。并且基于该体系,提供了ActionEvent与ValueChangeEvent两套实现,供应用开发程序员使用。下面我们先来看一下最基本的FacesEvent的五要素:

a. 事件类型
FacesEvent。这是一种依附在组件上,为组件服务的事件。其事件源为组件实例。

b. 监听方注册方式
通过调用组件实例上的addFacesListener方法注册监听器。监听器必须实现FacesListener接口。默认情况下,注册到组件上的监听器会被看作是组件的附加对象(AttachedObject),在ViewState中保存状态。因此FacesListener的实现类必须有一个public的无参构造器,有状态的监听器应该实现StateHolder接口。针对不同的FacesEvent子类(见下文c),可能需要特定的FacesListener具体类与之对应。因此在UIComponent.addFacesListener()方法上,用javadoc建议具体的组件实现应该提供强类型的接口方法,接受具体的FacesListener子类作为参数。
引用
发表评论
用户名: 匿名