Unterschiede zwischen Aktion und Action
-
29-09-2019 - |
Frage
Was ist der Unterschied zwischen action
und actionListener
, und wann sollte ich verwenden action
gegen actionListener
?
Lösung
Action
Verwenden actionListener
, wenn Sie einen Haken haben wollen vor die eigentliche Geschäft Aktion ausgeführt werden soll, zum Beispiel zu protokollieren und / oder eine zusätzliche Eigenschaft zu setzen (durch ActionEvent
Argument). Also, rein für die Vorbereitung Zwecke vor der eigentlichen Geschäft Aktion aufgerufen wird.
Die actionListener
Methode hat standardmäßig die folgende Signatur:
import javax.faces.event.ActionEvent;
// ...
public void actionListener(ActionEvent event) {
// ...
}
Und es soll erklärt werden, wie folgt, ohne Verfahren Klammern:
<h:commandXxx ... actionListener="#{bean.actionListener}" />
Beachten Sie, dass Sie nicht passieren können zusätzliche Argumente von EL 2.2. Sie können jedoch die ActionEvent
Argument außer Kraft zusammen, indem und benutzerdefinierte Argument Angabe (n). Die folgenden Beispiele gelten:
<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) {}
Beachten Sie die Bedeutung der Klammern in dem argument Methode Ausdruck. Wenn sie nicht vorhanden wären, würde JSF noch ein Verfahren mit ActionEvent
Argumente erwartet.
Wenn Sie auf EL sind 2.2+, dann können Sie mehrere Aktion Listener-Methoden über <f:actionListener binding>
erklären.
<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() {}
Beachten Sie die Bedeutung der Klammern im binding
Attribute. Wenn sie nicht vorhanden wäre, würde EL verwechselbar eine javax.el.PropertyNotFoundException: Property 'actionListener1' not found on type com.example.Bean
werfen, weil das binding
Attribut standardmäßig als Wert Ausdruck interpretiert, nicht als Methode Ausdruck. Hinzufügen EL 2.2+ Stil Klammern dreht transparent Wert Ausdruck in eine Methode Ausdruck. Siehe auch u.a. Warum Uhr ich in der Lage zu binden
Aktion
Mit action
wenn Sie ein Geschäft Aktion und ggf. Griff Navigation ausgeführt werden soll. Die action
Verfahren können (also nicht muss) liefern einen String
der als Navigations Fall Ergebnis verwendet wird (die Zielansicht). Ein Rückgabewert von null
oder void
wird es auf die gleiche Seite zurückkehren lassen und die aktuelle Ansicht Umfang am Leben zu halten. Ein Rückgabewert von einer leeren Zeichenfolge oder der gleichen Ansicht ID kehrt auch auf die gleiche Seite, aber die Ansicht Umfang neu erstellen und somit alle derzeit aktive Ansicht scoped Bohnen zerstören und ggf. neu erstellen.
Die action
Methode kann jeder gültige MethodExpression
diejenigen, auch die verwendet EL 2.2 Argumente wie folgt:
<h:commandXxx value="submit" action="#{bean.edit(item)}" />
Mit dieser Methode:
public void edit(Item item) {
// ...
}
Beachten Sie, dass, wenn Ihre Aktion-Methode nur einen String zurückgibt, dann können Sie auch angeben, nur genau diese Zeichenfolge im action
Attribut. Somit ist dies völlig ungeschickt:
<h:commandLink value="Go to next page" action="#{bean.goToNextpage}" />
Mit dieser sinnlosen Methode eines hartcodierte Zeichenfolge Rückkehr:
public String goToNextpage() {
return "nextpage";
}
Stattdessen nur setzen, dass fest einprogrammiert String direkt im Attribute:
<h:commandLink value="Go to next page" action="nextpage" />
Bitte beachten Sie, dass dies wiederum ein schlechtes Design zeigt an: Navigieren durch POST. Dies ist nicht vom Benutzer noch SEO freundlich. Dies alles wird erklärt in Wann sollte ich h verwenden: outputLink statt h: command und sollte als lösenden
<h:link value="Go to next page" outcome="nextpage" />
Siehe auch Wie in JSF navigieren? Wie URL reflektiert aktuelle Seite (und nicht die vorherigen) zu machen.
f: ajax Hörer
Da JSF 2.x gibt es eine dritte Möglichkeit, die <f:ajax listener>
.
<h:commandXxx ...>
<f:ajax listener="#{bean.ajaxListener}" />
</h:commandXxx>
Die ajaxListener
Methode hat standardmäßig die folgende Signatur:
import javax.faces.event.AjaxBehaviorEvent;
// ...
public void ajaxListener(AjaxBehaviorEvent event) {
// ...
}
In Mojarra, das AjaxBehaviorEvent
Argument ist optional, unter Arbeiten so gut.
public void ajaxListener() {
// ...
}
Aber in MyFaces, wäre es ein MethodNotFoundException
werfen. Im Folgende Arbeiten in beiden JSF-Implementierungen, wenn Sie das Argument weglassen.
<h:commandXxx ...>
<f:ajax execute="@form" listener="#{bean.ajaxListener()}" render="@form" />
</h:commandXxx>
Ajax Zuhörer sind nicht wirklich nützlich auf Befehlskomponenten. Sie sind nützlich bei der Eingabe und wählen Sie Komponenten <h:inputXxx>
/ <h:selectXxx>
. In Befehlskomponenten, bleibt nur action
und / oder actionListener
für Klarheit und besseren Selbst dokumentiert Code. Darüber, wie actionListener
, wird der f:ajax listener
kein Navigations Ergebnis unterstützen zurück.
<h:commandXxx ... action="#{bean.action}">
<f:ajax execute="@form" render="@form" />
</h:commandXxx>
Zur Erklärung auf execute
und render
Attributen, den Kopf auf Verstehen PrimeFaces verarbeiten / update und JSF f: ajax ausführen / render Attribute
Invocation Ordnung
Die actionListener
s werden immer aufgerufen vor die action
in der gleichen Reihenfolge, wie sie in der Ansicht und an die Komponente deklariert worden. Die f:ajax listener
wird immer aufgerufen vor jede Aktion Hörer. Also, das folgende Beispiel:
<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>
Werden die Methoden in der folgenden Reihenfolge aufrufen:
-
Bean#ajaxListener()
-
Bean#actionListener()
-
ActionListenerType#processAction()
-
Bean#actionListenerBinding()
-
Bean#setProperty()
-
Bean#action()
Ausnahmebehandlung
Die actionListener
unterstützt eine spezielle Ausnahme: AbortProcessingException
. Wenn diese Ausnahme von einer actionListener
Methode geworfen wird, dann werden alle verbleibenden JSF Aktion Zuhörer überspringen und die Aktionsmethode und gehen Reaktion direkt zu machen. Sie werden keinen Fehler / Ausnahme-Seite, JSF wird es jedoch loggt sein. Dies wird auch implizit erfolgen, wenn eine andere Ausnahme von einem actionListener
geworfen wird. Also, wenn Sie beabsichtigen, die Seite durch eine Fehlerseite als Ergebnis eines Unternehmen Ausnahme zu blockieren, dann sollten Sie auf jeden Fall den Job in dem action
Verfahren.
Wenn der einzige Grund, eine actionListener
zu verwenden ist ein void
Verfahren zu haben, auf die gleiche Seite zurückkehrt, dann ist das ein schlechter. Die action
Methoden lassen sich perfekt auch void
zurückkehren, im Gegenteil zu dem, was einige IDEs können Sie über EL Validierung glauben. Beachten Sie, dass die PrimeFaces Vitrine Beispiele mit dieser Art von actionListener
s über allen Platz übersät sind. Dies ist in der Tat falsch. Tun Sie dies nicht als Vorwand benutzen, um auch, dass selbst tun.
In AJAX-Anfragen jedoch ein besonderer Ausnahme-Handler benötigt. Dies ist unabhängig davon, ob Sie listener
Attribut <f:ajax>
verwenden oder nicht. Zur Erklärung und ein Beispiel, den Kopf auf Exception in JSF Umgang mit AJAX-Anforderungen .
Andere Tipps
Wie BalusC angegeben, die actionListener
durch Standard schlucken Ausnahmen, aber in JSF 2.0 gibt es ein wenig mehr dazu. Das heißt, es funktioniert nicht nur Schwalben und Protokolle, aber eigentlich publiziert die Ausnahme.
Dies geschieht durch einen Aufruf wie folgt aus:
context.getApplication().publishEvent(context, ExceptionQueuedEvent.class,
new ExceptionQueuedEventContext(context, exception, source, phaseId)
);
Der Standard-Listener für dieses Ereignis ist die ExceptionHandler
für Mojarra, die auf com.sun.faces.context.ExceptionHandlerImpl
gesetzt. Diese Implementierung wird rethrow grundsätzlich jede Ausnahme, es sei denn, es handelt sich um eine AbortProcessingException, der angemeldet ist. ActionListeners die Ausnahme wickeln, die von der Client-Code in einer solchen AbortProcessingException geworfen wird, was erklärt, warum diese immer angemeldet sind.
Diese ExceptionHandler
können jedoch in faces-config.xml mit einer benutzerdefinierten Implementierung ersetzt werden:
<exception-handlerfactory>
com.foo.myExceptionHandler
</exception-handlerfactory>
Statt global hören, eine einzelne Bohne kann auch auf diese Ereignisse hören. Im Folgenden ist ein Proof of Concept dies:
@ManagedBean
@RequestScoped
public class MyBean {
public void actionMethod(ActionEvent event) {
FacesContext.getCurrentInstance().getApplication().subscribeToEvent(ExceptionQueuedEvent.class, new SystemEventListener() {
@Override
public void processEvent(SystemEvent event) throws AbortProcessingException {
ExceptionQueuedEventContext content = (ExceptionQueuedEventContext)event.getSource();
throw new RuntimeException(content.getException());
}
@Override
public boolean isListenerForSource(Object source) {
return true;
}
});
throw new RuntimeException("test");
}
}
(beachten Sie, das ist nicht, wie man sollte in der Regel Code Zuhörer, dass dies nur zu Demonstrationszwecken!)
Der Aufruf dieses von einem Facelet wie folgt aus:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:body>
<h:form>
<h:commandButton value="test" actionListener="#{myBean.actionMethod}"/>
</h:form>
</h:body>
</html>
Ergebnis wird in einer Fehlerseite angezeigt wird.
Action zuerst gefeuert wird, mit der Option, die Antwort zu ändern, bevor Aktion aufgerufen wird und bestimmt die Position der nächsten Seite.
Wenn Sie mehrere Tasten auf der gleichen Seite haben, die an den gleichen Ort gehen sollte, aber tun etwas andere Dinge, können Sie die gleiche Aktion für jede Taste verwenden, aber eine andere Action verwenden etwas andere Funktionalität zu behandeln.
Hier ist ein Link, der die Beziehung beschreibt:
http://www.java-samples.com/showtutorial.php? tutorialid = 605
TL; DR :
Die ActionListener
s (es können mehrere sein) ausführen in der Reihenfolge, wie sie VOR dem action
registriert wurden
Lange Antwort: :
Ein Business action
ruft typischerweise einen EJB-Service und bei Bedarf setzt auch das Endergebnis und / oder navigiert zu einer anderen Ansicht
wenn es das ist nicht das, was Sie actionListener
tun, ist besser geeignet, dh für, wenn der Benutzer interagiert mit den Komponenten, wie h:commandButton
oder h:link
sie können, indem man den Namen der verwalteten Bean-Methode in actionListener
Attribute einer UI-Komponente behandelt werden oder eine ActionListener
-Schnittstelle implementieren und die Implementierungsklasse Namen actionListener
Attribut einer UI-Komponente übergeben.