jsf
前言
JSF模拟了传统的C/S编程模式,它隐藏了传统Web变成的请求——响应通信模式,而是模拟了C/S变成中的事件通信机制。今天就了解一下JSF的事件机制
事件机制概述
在JSF(一)中提到了,JSF的标签定了一强大的服务器组件,而且他允许组件直接和托管Bean进行绑定,而在托管Bean中定义的方法可以处理Action事件、处理值改变事件等。这就是JSF提供的事件机制
java事件模型概述
EventSource(事件源):事件发生的场所,通常就是各个组件
Event(事件):事件封装了GUI组件上发生的特定事件(通常就是一次用户操作)
Event Listener(事件监听器):负责监听事件源所发生的事件,并对各种事件做出相应的响应
现在回想一下我们在敲C/S版机房的时候,是不是点击按钮,直接可以到达click的方法,方法可以独立的存在,但是在Java的世界中,方法必须放到类中,用类来将一系列的方法组织起来
而事件监听器就是这个包含了很多响应事件方法的类,这些方法也被称为事件处理器(Event handler)。当事件源上的事件发生时,事件对象会作为参数传给事件处理器
委派事件处理方式
普通组件(事件源)将整个事件处理委托给特定的对象(事件监听器);当该事件源发生指定的事件时,就通知所委托的事件监听器,由事件监听器来处理这个事件
每个组件可以针对特定的事件制定一个或多个事件监听对象,每个事件监听器也可监听一个或多个事件源。因为同一个事件源上可能发生的事件分别授权给不同的事件监听器来处理;同时也可以让一类事件都使用同一个事件监听器来处理
P.S. 在书上看到一个对委派式事件处理方式的联系实际的说法,这种方式很像是人类社会的分工协作,例如某个单位发生了火灾,该单位通常不会自己处理该事件,而是将该事件委派给消防局(事件监听器)处理;如果发生了打架斗殴事件,则为拍给公安局处理;而消防局、公安局也会同时监听多个单位的火灾、打架斗殴事件。
JSF事件模型
三部分:
事件源:JSF页面上所有UI组件都可以作为事件源
事件对象:当用户对UI组件执行动作时,JSF会为之创建对应的事件对象
事件监听器:JSF的事件监听器比较灵活,既可直接托管Bean的某个方法来处理用户事件,也可使用专门的事件监听器对象
4种事件对象:
- Action对象:当用户单击某个commandButton或commandLink标签生成的组件时,JSF将会触发Action事件
- 值改变事件:用户在输入框中输入数据导致UI组件的本地值发生改变时触发
- 数据模型事件:由UIData组件触发,当数据表的某行被选中时触发
- 生命周期事件:当JSF应用的生命周期从一个阶段进入另一个阶段是触发
Java事件机制和JSF时间机制异同
分别总结完两者的事件机制,会发现他们十分相似,
不同点:
1. Java事件机制,会使用addXXXListener方法来注册,但是JSF会采用自定义标签+配置文件的方式进行注册
public void init(){
//Java事件机制注册事件监听器
ok.addactionlistener(new OkListener());
f.add(tf);
f.add(ok,Borderlayout.SOUTH);
f.pack();
f.setVisible(true);
}
//
<h:commandLink id="Duke" action="bookstore">
<!--Jsf中的注册事件监听器-->
<f:actionListener
type="javaeetutorial.dukesbookstore.listeners.LinkBookChangeListener" />
<h:outputText value="#{bundle.Book201}"/>
</h:commandLink>
2. Java事件中事件监听器必须实现一个独立的监听类,但JSF事件机制则允许直接使用托管Bean中某个方法作为事件处理方法。唯一的要求是该方法必须使用特定的方法签名
Action事件对应的事件处理方法的方法签名是:
public void XXX(ActionEvent event)
栗子:
public void processAction(ActionEvent event)
throws AbortProcessingException {
logger.log(Level.INFO, "Entering LinkBookChangeListener.processAction");
String current = event.getcomponent().getId();
Facescontext context = FacesContext.getCurrentinstance();
String bookId = books.get(current);
context.getExternalContext().getsessionMap().put("bookId", bookId);
}
一旦托管Bean类中提供了满足上面签名的事件处理方法后,接下来就可以通过为UI标签增加如下两个属性来绑定事件处理方法:
actionListener:该属性的属性只是一个方法表达式,用于绑定Action事件的事件处理方法
valueChangListener:该属性的属性值是一个方法表达式,用于绑定值改变时间的事件处理方法
class: LinkBookChangeListener中的提供的签名方法
//class:MapBookChangeListener中的提供的签名方法
public void processAction(ActionEvent event)
throws AbortProcessingException {
logger.log(Level.INFO, "Entering LinkBookChangeListener.processAction");
String current = event.getComponent().getId();
FacesContext context = FacesContext.getCurrentInstance();
String bookId = books.get(current);
context.getExternalContext().getSessionMap().put("bookId", bookId);
}
页面中的绑定的Action事件处理的方法:
<h:commandLink id="Duke" action="bookstore">
<f:actionListener
type="javaeetutorial.dukesbookstore.listeners.LinkBookChangeListener" />
<h:outputText value="#{bundle.Book201}"/>
</h:commandLink>
总结
今天总结了一下两种事件机制,看似都是没有学过的新知识,但是你会发现其实和原来的思想有很多共同之处,只是实现方式不同而已,下一篇将会详细的介绍JSF两种事件响应:ActionEvent,ValueChangeEvent