Jaka jest różnica między action
i actionListener
, i kiedy należy użyć action
kontra actionListener
?
źródło
Jaka jest różnica między action
i actionListener
, i kiedy należy użyć action
kontra actionListener
?
Użyj, actionListener
jeśli chcesz mieć hak przed wykonaniem prawdziwej akcji biznesowej, np. Aby ją zarejestrować i / lub ustawić dodatkową właściwość (by <f:setPropertyActionListener>
) i / lub mieć dostęp do komponentu, który wywołał akcję (który jest dostępny przez ActionEvent
argument). Zatem wyłącznie w celu przygotowania celów przed wywołaniem prawdziwej akcji biznesowej.
actionListener
Metoda ma domyślnie następujący podpis:
import javax.faces.event.ActionEvent;
// ...
public void actionListener(ActionEvent event) {
// ...
}
I powinien być zadeklarowany w następujący sposób, bez nawiasów metod:
<h:commandXxx ... actionListener="#{bean.actionListener}" />
Zauważ, że nie możesz przekazać dodatkowych argumentów przez EL 2.2. Możesz jednak ActionEvent
całkowicie zastąpić argument, przekazując i określając niestandardowe argumenty. Poprawne są następujące przykłady:
<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) {}
Zwróć uwagę na znaczenie nawiasów w wyrażeniu metody bez argumentów. Gdyby ich nie było, JSF nadal oczekiwałby metody z ActionEvent
argumentami.
Jeśli korzystasz z EL 2.2+, możesz zadeklarować wiele metod nasłuchiwania akcji za pośrednictwem <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() {}
Zwróć uwagę na znaczenie nawiasów w binding
atrybucie. Gdyby były nieobecne, EL myląco rzuciłoby a javax.el.PropertyNotFoundException: Property 'actionListener1' not found on type com.example.Bean
, ponieważ binding
atrybut jest domyślnie interpretowany jako wyrażenie wartości, a nie jako wyrażenie metody. Dodanie nawiasów w stylu EL 2.2+ powoduje, że wyrażenie wartości staje się wyrażeniem metody. Zobacz także: Dlaczego mogę powiązać <f: actionListener> z dowolną metodą, jeśli nie jest obsługiwana przez JSF?
Użyj, action
jeśli chcesz wykonać akcję biznesową i, jeśli to konieczne, obsługiwać nawigację. action
Sposób może (a więc nie musi) zwracają String
, które będą stosowane jako wynik przypadku nawigacji (widok z góry docelowy). Zwracana wartość null
lub void
umożliwia powrót do tej samej strony i utrzymanie bieżącego zakresu widoku. Zwracana wartość pustego ciągu lub tego samego identyfikatora widoku również powróci na tę samą stronę, ale odtworzy zakres widoku, a tym samym zniszczy wszystkie aktywne komponenty bean o zasięgu widoku i, jeśli to konieczne, odtworzy je.
action
Metoda może być jakieś ważne MethodExpression
, także te, które wykorzystuje EL 2.2 argumenty takie jak poniżej:
<h:commandXxx value="submit" action="#{bean.edit(item)}" />
Dzięki tej metodzie:
public void edit(Item item) {
// ...
}
Zauważ, że gdy metoda akcji zwraca tylko ciąg znaków, możesz również dokładnie określić dokładnie ten ciąg w action
atrybucie. Jest to zatem całkowicie niezdarne:
<h:commandLink value="Go to next page" action="#{bean.goToNextpage}" />
Za pomocą tej bezsensownej metody zwracania zakodowanego ciągu:
public String goToNextpage() {
return "nextpage";
}
Zamiast tego po prostu umieść ten zakodowany ciąg bezpośrednio w atrybucie:
<h:commandLink value="Go to next page" action="nextpage" />
Pamiętaj, że to z kolei oznacza zły projekt: nawigacja POST. To nie jest przyjazny dla użytkownika ani SEO. Wszystko to wyjaśniono w rozdziale Kiedy powinienem używać h: outputLink zamiast h: commandLink? i ma być rozwiązany jako
<h:link value="Go to next page" outcome="nextpage" />
Zobacz także Jak nawigować w JSF? Jak sprawić, by adres URL odzwierciedlał bieżącą stronę (a nie poprzednią) .
Od JSF 2.x istnieje trzeci sposób, czyli <f:ajax listener>
.
<h:commandXxx ...>
<f:ajax listener="#{bean.ajaxListener}" />
</h:commandXxx>
ajaxListener
Metoda ma domyślnie następujący podpis:
import javax.faces.event.AjaxBehaviorEvent;
// ...
public void ajaxListener(AjaxBehaviorEvent event) {
// ...
}
W Mojarra AjaxBehaviorEvent
argument jest opcjonalny, poniżej działa tak samo dobrze.
public void ajaxListener() {
// ...
}
Ale w MyFaces rzuciłoby MethodNotFoundException
. Poniżej działa w obu implementacjach JSF, jeśli chcesz pominąć argument.
<h:commandXxx ...>
<f:ajax execute="@form" listener="#{bean.ajaxListener()}" render="@form" />
</h:commandXxx>
Detektory Ajax nie są tak naprawdę przydatne w komponentach poleceń. Są bardziej przydatne przy wprowadzaniu i wybieraniu komponentów <h:inputXxx>
/ <h:selectXxx>
. W komponentach poleceń po prostu trzymaj się action
i / lub actionListener
w celu uzyskania przejrzystości i lepszego samodokumentowania kodu. Ponadto, podobnie jak actionListener
, f:ajax listener
nie obsługuje zwracania wyniku nawigacji.
<h:commandXxx ... action="#{bean.action}">
<f:ajax execute="@form" render="@form" />
</h:commandXxx>
Aby uzyskać wyjaśnienie execute
i render
atrybuty, przejdź do Zrozumienie procesu / aktualizacji PrimeFaces i JSF f: ajax atrybuty wykonania / renderowania .
Do actionListener
s zawsze są wywoływane przedaction
w tej samej kolejności, jak są one zostały uznane w widoku i dołączone do komponentu. f:ajax listener
Zawsze jest wywoływana przed każdym słuchaczem działania. Tak więc następujący przykład:
<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>
Wywoła metody w następującej kolejności:
Bean#ajaxListener()
Bean#actionListener()
ActionListenerType#processAction()
Bean#actionListenerBinding()
Bean#setProperty()
Bean#action()
actionListener
Obsługuje specjalny wyjątek: AbortProcessingException
. Jeśli ten wyjątek zostanie zgłoszony z actionListener
metody, JSF pominie pozostałe nasłuchiwania akcji i metodę akcji i przejdzie bezpośrednio do renderowania odpowiedzi. Nie zobaczysz strony błędu / wyjątku, jednak JSF ją zarejestruje. Będzie to również domyślnie wykonane za każdym razem, gdy zostanie zgłoszony jakikolwiek inny wyjątek od actionListener
. Jeśli więc zamierzasz zablokować stronę za pomocą strony błędu w wyniku wyjątku biznesowego, zdecydowanie powinieneś wykonać zadanie w action
metodzie.
Jeśli jedynym powodem użycia an actionListener
jest void
powrót metody do tej samej strony, to źle. Te action
metody mogą doskonale również powrócić void
, przeciwnie do tego, co niektórzy IDE pozwalają wierzyć poprzez walidację EL. Zauważ, że przykłady prezentacji PrimeFaces są zaśmiecone tego rodzaju literamiactionListener
wszędzie. To jest rzeczywiście złe. Nie używaj tego jako pretekstu, aby zrobić to sam.
Jednak w żądaniach ajax potrzebna jest specjalna procedura obsługi wyjątków. Jest to niezależne od tego, czy używasz listener
atrybutu, <f:ajax>
czy nie. Aby uzyskać wyjaśnienie i przykład, przejdź do Obsługa wyjątków w żądaniach JSF ajax .
actionListener
zgłaszanych wyjątków , ale nadal nie stanowi to dobrej wymówki do nadużyćactionListener
w działaniach biznesowych .action
odpowiada.actionListener
jest na drugorzędne rzeczy. Chciałem tylko wyjaśnić, że wactionListener
razie potrzeby można propagować wyjątki od s;)actionListener
atrybucie, i tak też musi byćpublic
.processAction
Nazwa jest obowiązkowa tylko gdy używasz<f:actionListener type>
, po prostu dlatego, że typ musi implementowaćActionListener
interfejs, który ma dokładnie to nazwa metodyprocessAction
zdefiniowana.<f:ajax>
wolisz w przypadku komponentów poleceń używaćaction
atrybutu do działań biznesowych. Np<h:commandButton action="#{bean.businessAction}"><f:ajax/></h:commandButton>
.Jak wskazał BalusC,
actionListener
domyślnie połyka wyjątki, ale w JSF 2.0 jest coś więcej. Mianowicie, nie tylko połyka i rejestruje, ale faktycznie publikuje wyjątek.Dzieje się tak przez takie połączenie:
Domyślnym detektorem tego zdarzenia jest ustawiony
ExceptionHandler
dla Mojarrycom.sun.faces.context.ExceptionHandlerImpl
. Ta implementacja zasadniczo zwróci każdy wyjątek, z wyjątkiem przypadków, gdy dotyczy wyjątku AbortProcessingException, który jest rejestrowany. ActionListeners zawijają wyjątek zgłaszany przez kod klienta w takim AbortProcessingException, który wyjaśnia, dlaczego są one zawsze rejestrowane.To
ExceptionHandler
może być zastąpiony jednak w twarze-config.xml z realizacji niestandardowych:Zamiast słuchać na całym świecie, jedna fasola może również słuchać tych wydarzeń. Oto dowód tego:
(uwaga: nie należy tak normalnie kodować słuchaczy, służy to wyłącznie do celów demonstracyjnych!)
Wywoływanie tego z Facelet takiego:
Powoduje wyświetlenie strony błędu.
źródło
ActionListener jest uruchamiany jako pierwszy, z opcją modyfikacji odpowiedzi, zanim Action zostanie wywołana i określi lokalizację następnej strony.
Jeśli masz wiele przycisków na tej samej stronie, które powinny iść w to samo miejsce, ale robisz nieco inne rzeczy, możesz użyć tej samej akcji dla każdego przycisku, ale użyć innej ActionListener do obsługi nieco innej funkcjonalności.
Oto link opisujący relację:
http://www.java-samples.com/showtutorial.php?tutorialid=605
źródło
TL; DR :
W
ActionListener
s (może być wielokrotnością) wykonać w kolejności ich zarejestrowanych przedaction
Długa odpowiedź :
Firma
action
zazwyczaj wywołuje usługę EJB i w razie potrzeby ustawia ostateczny wynik i / lub przechodzi do innego widoku, jeśli nie to, co robisz,actionListener
jest bardziej odpowiednie, tj. Gdy użytkownik wchodzi w interakcję z komponentami, takimi jakh:commandButton
lubh:link
może być obsługiwany przez przekazanie nazwy metody zarządzanegoactionListener
komponentu bean w atrybucie komponentu interfejsu użytkownika lub w celu zaimplementowaniaActionListener
interfejsu i przekazania nazwy klasy implementacji doactionListener
atrybutu komponentu interfejsu użytkownika.źródło