Question

Quelle est la différence entre action et actionListener, et quand dois-je utiliser action contre actionListener?

Était-ce utile?

La solution

actionListener

Utilisez actionListener si vous voulez avoir un crochet avant la vraie action entreprise s'exécuter, par exemple pour se connecter, et / ou pour une propriété supplémentaire (par <f:setPropertyActionListener> ), et / ou d'avoir accès au composant qui a invoqué l'action (qui est disponible par ActionEvent argument). Ainsi, uniquement pour la préparation des fins avant que l'action réelle des entreprises s'invoqué.

La méthode de actionListener a par défaut la signature suivante:

import javax.faces.event.ActionEvent;
// ...

public void actionListener(ActionEvent event) {
    // ...
}

Et il est censé être déclaré comme suit, sans parenthèses méthode:

<h:commandXxx ... actionListener="#{bean.actionListener}" />

Notez que vous ne pouvez pas passer supplémentaires arguments avancés par EL 2.2. Vous pouvez cependant passer outre l'argument ActionEvent tout à fait en passant et en spécifiant l'argument personnalisé (s). Les exemples suivants sont valables:

<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) {}

Notez l'importance des parenthèses dans l'expression de la méthode argumentless. S'ils étaient absents, JSF attendre encore une méthode avec l'argument de ActionEvent.

Si vous êtes sur EL 2.2+, vous pouvez déclarer plusieurs méthodes d'écouteur d'action via <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() {}

Notez l'importance des parenthèses dans l'attribut binding. S'ils étaient absents, EL serait de prêter à confusion jeter un javax.el.PropertyNotFoundException: Property 'actionListener1' not found on type com.example.Bean, parce que l'attribut binding est par défaut interprété comme une expression de valeur, et non comme une expression de la méthode. Ajout des parenthèses de style de EL se transparente une expression de valeur dans une expression de la méthode. Voir aussi A.O. Pourquoi est-ce Je capable de se lier ? une méthode arbitraire si elle est pas pris en charge par JSF


Action

Utilisez action si vous voulez exécuter une action commerciale et si nécessaire poignée de navigation. La méthode peut action (donc, ne doit pas) retourner un String qui sera utilisé comme résultat de cas de navigation (la vue cible). Une valeur de retour de null ou void va le laisser revenir à la même page et garder la vue actuelle portée en vie. Une valeur de retour d'une chaîne vide ou le même ID de vue également revenir à la même page, mais recréer la portée de vue et ainsi détruire toute vue active scope haricots et, le cas échéant, de les recréer.

La méthode de action peut être tout valide MethodExpression , aussi ceux qui utilisent EL 2,2 arguments comme ci-dessous:

<h:commandXxx value="submit" action="#{bean.edit(item)}" />

Avec cette méthode:

public void edit(Item item) {
    // ...
}

Notez que lorsque votre méthode d'action retourne uniquement une chaîne, vous pouvez aussi simplement spécifier exactement cette chaîne dans l'attribut action. Ainsi, ce qui est totalement maladroit:

<h:commandLink value="Go to next page" action="#{bean.goToNextpage}" />

Avec cette méthode insensée retournant une chaîne hardcoded:

public String goToNextpage() {
    return "nextpage";
}

Au lieu de cela, il suffit de mettre cette chaîne directement dans l'attribut hardcoded:

<h:commandLink value="Go to next page" action="nextpage" />

S'il vous plaît noter que ce à son tour indique une mauvaise conception: la navigation par POST. Ce n'est pas utilisateur ni SEO friendly. Tout cela est expliqué dans Quand dois-je utiliser h: outputLink au lieu de h: commandLink et est censé être résolu comme

<h:link value="Go to next page" outcome="nextpage" />

Voir aussi Comment naviguer dans JSF? Comment URL faire réfléchir la page en cours (et non précédent) .


f: ajax auditeur

Depuis JSF 2.x, il y a une troisième voie, la <f:ajax listener>.

<h:commandXxx ...>
    <f:ajax listener="#{bean.ajaxListener}" />
</h:commandXxx>

La méthode de ajaxListener a par défaut la signature suivante:

import javax.faces.event.AjaxBehaviorEvent;
// ...

public void ajaxListener(AjaxBehaviorEvent event) {
    // ...
}

Dans Mojarra, l'argument est AjaxBehaviorEvent en option, ci-dessous fonctionne comme bon.

public void ajaxListener() {
    // ...
}

Mais MyFaces, il jetterait un MethodNotFoundException. Ci-dessous, dans les deux œuvres mises en œuvre JSF lorsque vous voulez omettre l'argument.

<h:commandXxx ...>
    <f:ajax execute="@form" listener="#{bean.ajaxListener()}" render="@form" />
</h:commandXxx>

auditeurs Ajax ne sont pas vraiment utiles sur les composants de commande. Ils sont plus utiles sur l'entrée et sélectionnez <h:inputXxx> / <h:selectXxx> composants. Dans les composants de commande, il suffit de coller à action et / ou actionListener pour plus de clarté et un meilleur code auto-documenté. De plus, comme actionListener, le f:ajax listener ne supporte pas le retour à un résultat de navigation.

<h:commandXxx ... action="#{bean.action}">
    <f:ajax execute="@form" render="@form" />
</h:commandXxx>

Pour plus d'explications sur les attributs de execute et render, tête comprendre traiter PrimeFaces / mise à jour et JSF f: Ajax exécuter / attributs rendent

.

pour Invocation

Les actionListeners sont toujours invoqué avant la action dans le même ordre que sont été déclarés dans la vue et attaché au composant. Le f:ajax listener est toujours invoqué avant tout auditeur d'action. Ainsi, l'exemple suivant:

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

invoquera les méthodes dans l'ordre suivant:

  1. Bean#ajaxListener()
  2. Bean#actionListener()
  3. ActionListenerType#processAction()
  4. Bean#actionListenerBinding()
  5. Bean#setProperty()
  6. Bean#action()

Gestion des exceptions

Le actionListener soutient une exception: AbortProcessingException . Si cette exception est levée à partir d'une méthode de actionListener, puis JSF sautera écouteurs d'action restants et la méthode d'action et de procéder à rendre une réponse directe. Vous ne verrez pas une page d'erreur / exception, JSF enregistre cependant il. Ce sera aussi implicitement fait à chaque fois une autre exception est lancée à partir d'un actionListener. Donc, si vous avez l'intention de bloquer la page par une page d'erreur à la suite d'une exception d'affaires, alors vous devriez certainement effectuer le travail dans la méthode action.

Si la seule raison d'utiliser un actionListener est d'avoir une méthode de void revenir à la même page, alors c'est une mauvaise. Les méthodes de action peuvent parfaitement revenir aussi void, au contraire à ce que certains IDEs vous croyez laisser via la validation EL. Notez que le PrimeFaces vitrine exemples sont jonchées de ce genre de actionListeners sur tout lieu. Ceci est en effet mal. Ne pas utiliser cela comme une excuse pour faire que vous.

Dans les requêtes ajax, cependant, un gestionnaire d'exception spéciale est nécessaire. Ceci est peu importe si vous utilisez l'attribut listener de <f:ajax> ou non. Pour une explication et un exemple, la tête Gestion des exceptions dans JSF ajax demandes .

Autres conseils

Comme indiqué BalusC, le actionListener par les exceptions par défaut, mais dans JSF 2.0, il est un peu plus à ce sujet. A savoir, il ne se contente pas des hirondelles et des journaux, mais en fait publie l'exception.

Cela se produit par un appel comme celui-ci:

context.getApplication().publishEvent(context, ExceptionQueuedEvent.class,                                                          
    new ExceptionQueuedEventContext(context, exception, source, phaseId)
);

L'écouteur par défaut pour cet événement est le ExceptionHandler qui, pour Mojarra est réglé sur com.sun.faces.context.ExceptionHandlerImpl. Cette mise en œuvre essentiellement réémettre une exception, sauf lorsqu'elle concerne un AbortProcessingException, qui est connecté. ActionListeners enveloppent l'exception qui est levée par le code client dans un tel AbortProcessingException ce qui explique pourquoi ils sont toujours enregistrés.

Cette ExceptionHandler peut être remplacé mais dans des faces-config.xml avec une implémentation personnalisée:

<exception-handlerfactory>
   com.foo.myExceptionHandler
</exception-handlerfactory>

Au lieu d'écouter le monde, un seul haricot peut également écouter ces événements. Ce qui suit est une preuve de concept de ceci:

@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");
    }

}

(note, ce n'est pas la façon dont on devrait normalement les auditeurs de code, cela est uniquement à des fins de démonstration!)

L'appel de cette d'un Facelet comme ceci:

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

entrainera dans une page d'erreur affiché.

ActionListener avait tiré le premier obtient, avec une option pour modifier la réponse, avant que l'action est appelée et détermine l'emplacement de la page suivante.

Si vous avez plusieurs boutons sur la même page qui devrait aller au même endroit, mais faire des choses légèrement différentes, vous pouvez utiliser la même action pour chaque bouton, mais utiliser un autre ActionListener pour gérer des fonctionnalités légèrement différentes.

Voici un lien qui décrit la relation:

http://www.java-samples.com/showtutorial.php? tutorialid = 605

TL; DR :

Les ActionListeners (il peut y avoir plusieurs) exécuter dans l'ordre ont été enregistrés avant le action

Réponse longue :

Une entreprise action invoque généralement un service EJB et si nécessaire définit également le résultat final et / ou accède à une vue différente si ce n'est pas ce que vous faites un actionListener est plus à-dire appropriée lorsque l'internaute interagit avec les composants, tels que h:commandButton ou h:link ils peuvent être manipulés en passant le nom de la méthode de bean géré en attribut actionListener d'un composant d'interface utilisateur ou mettre en œuvre une interface ActionListener et de transmettre le nom de classe d'implémentation d'attribut actionListener d'un composant d'interface utilisateur.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top