OperaMasks事件处理模型与其他大多数Web开发技术不同,它提供了基于事件的编程模型,与传统的GUI程序(如Swing)类似。使用OperaMasks事件模型,就不再需要考虑处理HTTP请求中大量的"键/值"对。相反,可以使用传统的事件模型编程,框架会把事件广播到每个监听器,调用监听器的处理逻辑。OperaMasks支持下列几种类型的事件:动作事件、值变化事件、阶段事件和AjaxAction事件。下面分别加以介绍。
动作事件一般是由命令构件触发的。比如当我们点击按钮或链接时,就会触发一个动作事件。这类能发起动作的构件实现了ActionSource或者ActionSource2接口。
先看一个例子,页面如下
<w:form>
<w:textField></w:textField>
<w:button action="#{bean.clickAction}"/>
</w:form>对应的LiteBean如下
public String clickAction() {
System.out.println("Button clicked!");
return null;
}点击按钮时,LiteBean对应的方法clickAction()方法被调用,在后台打印出"Button clicked"字符串。现在我们看看,点击按钮时,整个处理流程是怎样的:
客户端提交表单,将HTTP Post请求发回服务器端。
服务器端进入请求处理生命周期,在应用请求值阶段,实例化一个ActionEvent对象,并把它作为参数传递给UICommand的 queueEvent() 方法将事件放入队列等候进一步处理。
应用请求值阶段结束后,进入处理验证和更新模型值阶段。如果这两个阶段都没有发生错误,那么进入调用应用程序阶段,将ActionEvent广播到对应的监听器,执行监听器的相关逻辑。
可见,我们只需提供ActionEvent对应的监听器,其他的事情请求处理生命周期处理会帮我们处理。一般来说,在OperaMasks中处理事件,可以编写监听器类实现合适的接口(对于动作事件,是javax.faces.event.ActionListener接口),并将监听器绑定到构件。对于动作事件,我们可以编写action方法或者actionListener方法。
对于命令构件,我们可以通过设置其action和actionListener属性指定监听器方法,如下
<w:button action="#{bean.action}" actionListener="#{bean.listener}"></w:button>当按钮被按下时,action和actionListener属性指定的方法都会被调用。但是,它们之间是有区别的:一般来说,action是为业务逻辑设计的,它不接受参数,并返回String参与导航处理(当返回Null时不进行导航处理);而actionListener通常完成用户界面逻辑,它接受一个ActionEvent作为参数,返回void,不参与导航。action方法一般如下
public String ation() {
// do something here
}而actionListener方法一般如下
public void actionListener(ActionEvent event) {
// do something here
}需要注意的是,action方法总在actionListener方法后调用。在 OperaMasks 中提供了几个事件相关注解@Action、@ActionListener和@ActionListeners等,可用IoVC方式绑定action方法和actionListener方法。详细请参看第 20 章 IoVC一节。
现在我们知道,动作事件监听器在调用应用程序阶段得到执行,在生命周期的处理验证和更新模型阶段之后调用,但是有时我们想在校验进行前调用监听器进行处理。例如,可能提供一个"取消"的按钮,在验证输入内容之前调用某个方法。要达到此目的,只需设置动作构件的immediate属性为true(默认为false)。
<w:form>
<w:textField required="true" id="field"></w:textField>
<w:button label="取消" immediate="true" action="#{bean.cancel}">
<w:button label="提交"
</w:form>设置了immediate属性为true的动作构件,监听器会提前到应用请求值阶段末尾执行,而不是在调用应用程序阶段执行。此时,由于更新模型值阶段没得到执行,如果想获得某个输入构件的值,可以在LiteBean绑定输入构件,使用 getSubmittedValue()() 来获得输入值。
@Bind
private UITextField field;
public String cancel() {
System.out.println(field.getSubmittedValue()());
return null;
}