2012年10月31日 星期三

JSF handlers 和 Listeners

一、Action Handllers 和 Event Listeners

點擊一個按鈕、超連結或者變更一個表單元件內的值通常需要某些類型的動作。多年以來,GUI 桌面應用程式針對事件處理已經提供了一套相當完善的事件處理定義模型,JSF 也提供了類似的機制。此類程式與 JSF 事件處理機制的主要區別在於: JSF 事件是由 client 端觸發,但在 server 端處理。

JSF 提供兩種方式來處理事件:listeners 和 action handlers,兩者皆可以定義於 managed beans 之內。listener 接受一個 FacesEvent 物件作為參數,其回傳型態則為 void;而 action handler 不接受任何參數,其回傳值的形態則為 String。listener 的一個好處是 FacesEvent 提供了額外的資訊,例如:觸發事件的表單(form)元件。Action handler 則不知道事件來源,但能根據回傳值來啟動頁面導覽(page navigation)。

二、Action Handlers

Action Handlers 通常用來作為頁面導覽。一個常見的用法是根據業務邏輯來處理表單的提交和新頁面導覽。頁面導覽由 Action Handler 的回傳值與 faces-config.xml 中定義的「navigation-rule」來決定。

讓我們來看一個例子:

<!--login.xhtml-->
<h:inputText id="username" />
<h:inputSecret id="password" />
<h:commandButton action="#{login.submitButtonAction}" type="submit" value=""Login />

<!--faces-config.xml-->
<navigation-rule>
  <form-view-id>/login.xhtml</form-view/-id>
  <navigation-case>
    <from-action>#{login.submitButtonAction}</from-action>
    <from-outcome>success</from-outcome>
    <to-view-id>/home.jsf</to-view-id>
  </navigation-case>
</navigation-rule>

<!--login/Login managedBean-->
public Srting submitButtonAction() {
 return "success";
}


在以上的例子中,使用者填寫完表單元件中的「username」和「password」欄位,然後按下 submit 按鈕(<h:commandButton>)。在「<h:commandButton>」的 action 屬性,指定了一個在 managedBean(submitButtonAction())中的 action handler,其回傳值為「success」。在 faces-config.xml 的 navigation rule 指定使用者將會被重導至「home.jsf」,在此先假設 FacesServlet 會被對映至 web.xml 中的「*.jsf」。

三、Event Listeners

當使用者點擊一個按鈕或鏈結、改變某欄位中的值,或從清單中選擇時,應用程式必須做出回應。透過應用程式的事件註冊機制,當 JSF 使用者介面元件發出一個使用者動作信號時,應用程式就會收到該事件的通知。

兩種最常見的 Event Listeners 是 action 和值的改變,但這並不包含其他像 data-model 與 phase。Listeners 可在 managed bean 或單獨的 listener class 之中宣告。將 listeners 置於一個單獨的 class 之中,可讓我們在多個 page views 之間重複使用。如果要建立一個 listener 的 class,該 class 必須實做 ActionListener 或 ValueChangeListener 介面。如前所述,一個 listener 只能接受一個 FacesEvent object 作為唯一的參數。FacesEvent 提供關於該事件的詳細資訊,例如觸發事件的表單元件,以及 JSF 生命週期的 phaseId。FacesEvent 有兩種子介面:ActionEventValueChangeEvent

1. ActionEvent

<h:commandButton> 和 <h:commandLink> 元件支援 actionListener 屬性。讓我們看一個例子:

<!--The page-->
<h:commandButton id="createUserSubmit" actionListener="#{createUser.submit_listener}" type="button" value="#Create User" />

<!-- createUser managedBean -->
public void submit_listener(Action ae) {
 System.out.println(ae.getId());
}


當使用者按下「Create User」按鈕(<h:commandButton)時,JSF 的實作會把該事件廣播給任何註冊的 listeners。在這個例子之中,在 createUser 這個 managed bean 的 listener  ——「submit_listener」將會被執行。另一種方式,是使用「actionListener」屬性的辦法,你可以使用 actionListener 標籤。

<h:commandButton id="createUserSubmit" type="button" value="#Create User">
 <f:actionListener type="com.interfrontier.ActionListenerImpl">
</h:commandButton>


這段代碼將會呼叫 ActionListenerImpl 的 processAction 方法。ActionListenerImpl 必須實作 ActionListener 介面,其定義了 processAction 方法:

public void processAction(ActionEvent vce) {
 System.out.println(vce.getId());
}


2. ValueChangeEvent

當某個元件的值改變時,而你希望被通知,例如 text 欄位的文字被修改或 checkbox 被選取時,那 ValueChangeEvent 就會非常有用。大部分的 JSF 元件都支援 valueChangeListener  屬性。讓我們來看一個例子:

<!-- The Page -->
<h:inputText id="name" valueChangeListener="createUser.nameChange_listener" />
<!-- createUser managedBean -->
public void nameChange_listener(ValueChangeEvent vce) {
 System.out.println(vce.getId());
 System.out.println(vce.getOldValue());
 System.out.println(vce.getNewValue());
}

當使用者修改表單中「name」欄位值的時候(<h:inputText>),JSF 實作就會將該事件廣播給任何註冊的 listeners。在這個例子之中, createUser 這個 managed bean 的 listener ——「nameChange_listener」將會被執行。注意 ValueChangeEvent 提供了該元件的原始值以及新(改變後)的值。

另外一種使用「valueChangeListener」屬性的辦法,是使用「valueChangeListener」這個標籤。

<h:inputText id="name">
  <f:valueChangeListener type="com.interfrontier.ValueChangeImpl"/>
</h:inputText>

這段代碼會呼叫 ValueChangeListenerImpl 的 processValueChange 方法。ValueChangeListenerImpl 必須實作 ValueChangeListener 介面,其定義了「processValueChange」方法。

public void processValueChange(ValueChangeEvent vce)
  throws AbortProcessingException {
    System.out.println(vce.getId());
    System.out.println(vce.getOldValue());
    System.out.println(vce.getNewValue());
}

四、結論:

Action Handlers 和 Event Listeners 是 JSF 用來提供事件驅動機制的重要特色。當使用者有任何動作時,例如點擊按鈕或提交表單時,就會發生一個事件。事件通知會透過 HTTP 送給 server,然後被 FacesServlet 處理,並呼叫自訂的業務邏輯或者啟動頁面導覽(page navigation)。

原文出處:http://johnderinger.wordpress.com/2007/10/10/action-handlers-and-event-listeners/