4 回答

TA貢獻1871條經(jīng)驗 獲得超13個贊
的ActionListener
使用actionListener
,如果你想有一個鉤子之前得到執(zhí)行的實際業(yè)務(wù)操作,如記錄它,和/或設(shè)置附加屬性(通過<f:setPropertyActionListener>
),和/或訪問其調(diào)用的動作(這是可以由組件ActionEvent
參數(shù))。因此,在實際業(yè)務(wù)操作被調(diào)用之前,純粹是為了準(zhǔn)備目的。
該actionListener
方法默認(rèn)具有以下簽名:
import javax.faces.event.ActionEvent;// ...public void actionListener(ActionEvent event) { // ...}
它應(yīng)該聲明如下,沒有任何方法括號:
<h:commandXxx ... actionListener="#{bean.actionListener}" />
請注意,您不能通過EL 2.2 傳遞其他參數(shù)。但是,您可以ActionEvent
通過傳遞和指定自定義參數(shù)來完全覆蓋參數(shù)。以下示例有效:
<h:commandXxx ... actionListener="#{bean.methodWithoutArguments()}" /><h:commandXxx ... actionListener="#{bean.methodWithOneArgument(arg1)}" /> <h:commandXxx ... actionListener="#{bean.methodWithTwoArguments(arg1, arg2)}" />
public void methodWithoutArguments() {}public void methodWithOneArgument(Object arg1) {}public void methodWithTwoArguments(Object arg1, Object arg2) {}
請注意無參數(shù)方法表達式中括號的重要性。如果它們不存在,JSF仍然期望一個帶ActionEvent
參數(shù)的方法。
如果您使用的是EL 2.2+,則可以通過聲明多個動作偵聽器方法<f:actionListener binding>
。
<h:commandXxx ... actionListener="#{bean.actionListener1}"> <f:actionListener binding="#{bean.actionListener2()}" /> <f:actionListener binding="#{bean.actionListener3()}" /></h:commandXxx>
public void actionListener1(ActionEvent event) {}public void actionListener2() {}public void actionListener3() {}
請注意binding
屬性中括號的重要性。如果它們不存在,EL會混淆地拋出一個javax.el.PropertyNotFoundException: Property 'actionListener1' not found on type com.example.Bean
,因為該binding
屬性默認(rèn)被解釋為值表達式,而不是方法表達式。添加EL 2.2+樣式括號透明地將值表達式轉(zhuǎn)換為方法表達式。另請參閱ao 為什么我能夠?qū)?lt;f:actionListener>綁定到任意方法(如果JSF不支持它)?
行動
使用action
,如果你想執(zhí)行業(yè)務(wù)操作,并在必要時處理導(dǎo)航。該action
方法可以(因此,不必)返回String
將用作導(dǎo)航案例結(jié)果(目標(biāo)視圖)的方法。返回值為null
或void
將使其返回到同一頁面并使當(dāng)前視圖范圍保持活動狀態(tài)。空字符串或相同視圖ID的返回值也將返回到同一頁面,但會重新創(chuàng)建視圖范圍,從而銷毀任何當(dāng)前活動的視圖范圍bean,并在適用時重新創(chuàng)建它們。
該action
方法可以是任何有效的MethodExpression
,也可以是使用EL 2.2參數(shù)的方法,如下所示:
<h:commandXxx value="submit" action="#{bean.edit(item)}" />
用這種方法:
public void edit(Item item) { // ...}
請注意,當(dāng)您的action方法僅返回一個字符串時,您也可以只在該action
屬性中指定該字符串。因此,這完全是笨拙的:
<h:commandLink value="Go to next page" action="#{bean.goToNextpage}" />
使用這種無意義的方法返回硬編碼字符串:
public String goToNextpage() { return "nextpage";}
相反,只需將該硬編碼字符串直接放在屬性中:
<h:commandLink value="Go to next page" action="nextpage" />
請注意,這反過來表明設(shè)計不好:通過POST導(dǎo)航。這不是用戶也不是SEO友好。這一切都在我何時應(yīng)該使用h:outputLink而不是h:commandLink?應(yīng)該被解決為
<h:link value="Go to next page" outcome="nextpage" />
另請參見如何在JSF中導(dǎo)航?如何使URL反映當(dāng)前頁面(而不是之前的頁面)。
f:ajax監(jiān)聽器
從JSF 2.x開始,第三種方式就是<f:ajax listener>
。
<h:commandXxx ...> <f:ajax listener="#{bean.ajaxListener}" /></h:commandXxx>
該ajaxListener
方法默認(rèn)具有以下簽名:
import javax.faces.event.AjaxBehaviorEvent;// ...public void ajaxListener(AjaxBehaviorEvent event) { // ...}
在Mojarra中,AjaxBehaviorEvent
參數(shù)是可選的,下面的效果很好。
public void ajaxListener() { // ...}
但是在MyFaces中,它會拋出一個MethodNotFoundException
。當(dāng)你想省略參數(shù)時,下面的兩個JSF實現(xiàn)都適用。
<h:commandXxx ...> <f:ajax execute="@form" listener="#{bean.ajaxListener()}" render="@form" /></h:commandXxx>
Ajax偵聽器在命令組件上并不真正有用。它們對輸入和選擇組件<h:inputXxx>
/ 更有用<h:selectXxx>
。在命令組件中,只需堅持action
和/或actionListener
清晰,以及更好的自我記錄代碼。而且,例如actionListener
,f:ajax listener
不支持返回導(dǎo)航結(jié)果。
<h:commandXxx ... action="#{bean.action}"> <f:ajax execute="@form" render="@form" /></h:commandXxx>
有關(guān)execute
和render
屬性的說明,請前往了解PrimeFaces進程/更新和JSF f:ajax執(zhí)行/渲染屬性。
調(diào)用順序
所述actionListener
s的總是調(diào)用之前的action
以相同的順序,因為它們是在視圖被聲明和連接到該組件。將f:ajax listener
始終調(diào)用之前的任何動作偵聽器。那么,以下示例:
<h:commandButton value="submit" actionListener="#{bean.actionListener}" action="#{bean.action}"> <f:actionListener type="com.example.ActionListenerType" /> <f:actionListener binding="#{bean.actionListenerBinding()}" /> <f:setPropertyActionListener target="#{bean.property}" value="some" /> <f:ajax listener="#{bean.ajaxListener}" /></h:commandButton>
將按以下順序調(diào)用方法:
Bean#ajaxListener()
Bean#actionListener()
ActionListenerType#processAction()
Bean#actionListenerBinding()
Bean#setProperty()
Bean#action()
異常處理
在actionListener
支持一個特殊的例外:AbortProcessingException
。如果從actionListener
方法拋出此異常,則JSF將跳過任何剩余的動作偵聽器和操作方法,并繼續(xù)直接呈現(xiàn)響應(yīng)。您不會看到錯誤/異常頁面,但JSF會記錄它。每當(dāng)從一個異常拋出任何其他異常時,也會隱式地執(zhí)行此操作actionListener
。因此,如果您打算通過錯誤頁面阻止頁面作為業(yè)務(wù)異常的結(jié)果,那么您肯定應(yīng)該在該action
方法中執(zhí)行該作業(yè)。
如果使用a的唯一理由actionListener
是讓void
方法返回到同一頁面,那么這是一個糟糕的方法。這些action
方法可以完美地返回void
,相反,某些IDE讓您通過EL驗證可以相信。請注意,PrimeFaces展示的例子actionListener
在所有地方都充滿了這種情況。這確實是錯的。不要以此為借口自己也這樣做。
但是,在ajax請求中,需要一個特殊的異常處理程序。這與您是否使用listener
屬性<f:ajax>
無關(guān)。有關(guān)解釋和示例,請轉(zhuǎn)到JSF ajax請求中的異常處理。

TA貢獻1895條經(jīng)驗 獲得超3個贊
TL; DR:
將ActionListener
在他們登記前的順序S(也可以是多個)執(zhí)行action
答案很長:
企業(yè)action
通常調(diào)用EJB服務(wù),并且如果必要的話也設(shè)置最終結(jié)果和/或?qū)Ш降讲煌囊晥D,如果這不是您正在做的事情actionListener
更合適,即當(dāng)用戶與組件交互時,例如h:commandButton
或者h:link
他們可以通過在actionListener
UI組件的屬性中傳遞托管bean方法的名稱或?qū)崿F(xiàn)ActionListener
接口并將實現(xiàn)類名稱傳遞actionListener
給UI組件的屬性來處理。
添加回答
舉報