Frage

Was ist der Unterschied zwischen action und actionListener, und wann sollte ich verwenden action gegen actionListener?

War es hilfreich?

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 ? auf eine beliebige Methode, wenn es nicht von JSF unterstützt


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 actionListeners 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:

  1. Bean#ajaxListener()
  2. Bean#actionListener()
  3. ActionListenerType#processAction()
  4. Bean#actionListenerBinding()
  5. Bean#setProperty()
  6. 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 actionListeners ü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 ActionListeners (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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top