Las diferencias entre la acción y el actionListener

¿Cuál es la diferencia entre action y actionListener, y cuando debo usar action frente a actionListener?

InformationsquelleAutor Murat Güzel | 2010-10-11

4 Kommentare

  1. 571

    actionListener

    Uso actionListener si quieres tener un gancho antes de el negocio real de la acción se ejecuta, por ejemplo, de registro, y/o para establecer una propiedad adicional (por <f:setPropertyActionListener>), y/o tener acceso a la parte que invoca la acción (que está disponible por ActionEvent argumento). Así, puramente para la preparación de los propósitos antes de que el verdadero negocio de acción se invoca.

    La actionListener método tiene por defecto la siguiente firma:

    import javax.faces.event.ActionEvent;
    //...
    
    public void actionListener(ActionEvent event) {
        //...
    }

    Y se supone que debe ser declarada de la siguiente manera, sin ningún método paréntesis:

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

    Tenga en cuenta que usted no puede pasar adicionales argumentos por EL 2.2. Sin embargo, puede anular la ActionEvent argumento totalmente por pasar y especificar custom argumento(s). Los ejemplos siguientes son válidas:

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

    Nota de la importancia de los paréntesis en la argumentless método de expresión. Si estaban ausentes, JSF sería de esperar de un método con ActionEvent argumento.

    Si estás en EL 2.2+, entonces usted puede declarar varias de acción de escucha de los métodos a través de <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() {}

    Nota de la importancia de los paréntesis en la binding atributo. Si estaban ausentes, EL iba a confusamente lanzar una javax.el.PropertyNotFoundException: Property 'actionListener1' not found on type com.example.Bean, porque el binding atributo de forma predeterminada, se interpreta como una expresión de valor, no como un método de expresión. Agregar EL 2.2+ estilo paréntesis de forma transparente se convierte en una expresión de valor en un método de expresión. Ver también.o. Por qué soy capaz de enlazar <f:actionListener> a un método arbitrario si no es compatible con JSF?


    acción

    Uso action si desea ejecutar un negocio de acción y, si es necesario controlar la navegación. El action método puede (por lo tanto, no debe) devuelven un String que serán utilizados para la navegación caso de resultado (a la vista de destino). Un valor de retorno de null o void le dejen regresar a la misma página y guardar la vista actual alcance vivo. Un valor de retorno de una cadena vacía o el mismo punto de vista de IDENTIFICACIÓN también regresar a la misma página, pero volver a la vista alcance y por lo tanto destruir cualquier vista actualmente activa ámbito de frijoles y, si procede, recreándolo.

    La action método puede ser cualquier válido MethodExpression, también los que utiliza EL 2.2 argumentos como el siguiente:

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

    Con este método:

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

    Tenga en cuenta que cuando su método de acción únicamente devuelve una cadena, entonces también puede especificar exactamente esa cadena en el action atributo. Por lo tanto, esta es totalmente torpe:

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

    Con esta absurda método devuelve una cadena codificada:

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

    Lugar, sólo hay que poner la cadena codificada directamente en el atributo:

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

    Por favor, tenga en cuenta que esto a su vez indica un mal diseño: navegando por el POST. Este no es el usuario, ni de SEO. Todo esto se explica en Cuando debo usar h:outputLink en lugar de h:commandLink? y se supone que se resuelve, como

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

    Ver también ¿Cómo navegar en JSF? Cómo hacer que la URL de reflejar la página actual (y no del anterior).


    f:ajax escucha

    Desde JSF 2.x hay un tercer camino, el <f:ajax listener>.

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

    La ajaxListener método tiene por defecto la siguiente firma:

    import javax.faces.event.AjaxBehaviorEvent;
    //...
    
    public void ajaxListener(AjaxBehaviorEvent event) {
        //...
    }

    En Mojarra, el AjaxBehaviorEvent argumento es opcional, a continuación funciona igual de bien.

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

    Pero en MyFaces, se lanzaría una MethodNotFoundException. A continuación funciona en ambas implementaciones de JSF cuando desee omitir el argumento.

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

    Ajax oyentes no son muy útiles a la orden de los componentes. Son más útiles en la entrada y seleccionar los componentes <h:inputXxx>/<h:selectXxx>. En el comando de componentes, sólo se adhieren a action y/o actionListener para una mayor claridad y una mejor auto-documentar el código. Por otra parte, como actionListener, el f:ajax listener no admite devolver un resultado de navegación.

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

    Para la explicación sobre execute y render atributos, de la cabeza a La comprensión de PrimeFaces y proceso de actualización y JSF f:ajax ejecutar y representar los atributos.


    Invocación fin de

    La actionListeners siempre se invoca antes de la action en el mismo orden en el que se ha declarado en la vista y que se adjunta a la componente. El f:ajax listener siempre se invoca antes de cualquier acción de escucha. Así, el siguiente ejemplo:

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

    Se invocan los métodos en el siguiente orden:

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

    Manejo de excepciones

    La actionListener admite una excepción especial: AbortProcessingException. Si esta excepción es lanzada desde un actionListener método, a continuación, JSF omitirá cualquier resto de la acción de los oyentes y el método de acción y proceder a procesar la respuesta directamente. Usted no verá un error/excepción de la página JSF sin embargo, se inicia la sesión. Esto también implícitamente ser realizado siempre de cualquier otra excepción se produce en un actionListener. Por lo tanto, si usted tiene la intención de bloquear la página por un error de la página como resultado de un negocio excepción, entonces usted definitivamente debe llevar a cabo el trabajo en el action método.

    Si la única razón para utilizar un actionListener es tener un void método de regresar a la misma página, entonces eso es una mala. El action métodos perfectamente puede también devolver void, por el contrario a lo que algunos IDEs hacerle creer a través de EL de validación. Tenga en cuenta que el PrimeFaces escaparate ejemplos están plagados de este tipo de actionListeners en todo lugar. Este es de hecho el mal. No utilizar esto como una excusa para hacer lo mismo.

    En peticiones ajax, sin embargo, una excepción especial para el controlador que se necesita. Esto es independientemente de si utiliza listener atributo de <f:ajax> o no. Para la explicación y un ejemplo, de la cabeza a Manejo de excepciones en JSF peticiones ajax.

    • Tienes razón que las excepciones en actionListeners son tragados por defecto, pero en JSF 2.0 este comportamiento puede ser modificado. Véase mi respuesta a continuación para obtener más detalles.
    • es verdad que el JSF 2.0 le permite cambiar el valor predeterminado de manejo de excepciones lanzadas por actionListener, pero que todavía no lo hace una buena excusa para el abuso actionListener para comerciales acciones.
    • De hecho, los negocios de las acciones están en el «flujo» de la petición/respuesta de ciclo y sólo el action corresponde con que. actionListener es para secundaria cosas. Sólo quería aclarar que las excepciones de actionListeners pueden ser reproducidos si así se requiere 😉
    • Hola BalusC, trato de confirmar su respuesta por escribir algo de código, pero el resultado es un poco extraño. Por favor, mire esta pregunta stackoverflow.com/questions/8683211/…?
    • Tenga en cuenta que el nombre de la clase de acción de la escucha de la firma es void processAction(ActionEvent event).
    • el nombre del método es de libre elección cuando se utiliza en actionListener atributo y tiene que ser public así. El processAction nombre sólo es obligatorio cuando usted está utilizando <f:actionListener type>, simplemente porque el tipo tiene que implementar ActionListener interfaz que tiene exactamente el nombre del método processAction definida.
    • Sí, por «nombre de la clase de acción escucha», me refería a la <f:actionListener> de la etiqueta (sin vacío).
    • puedo preguntar, ¿cuál sería el orden de ejecución se si hay un anidada f:ajax con un detector de atributo, cómo sería el flujo de ejecución de ir?
    • ajax acción oyente se invoca antes de que todos los regulares de la acción de los oyentes. Tenga en cuenta que incluso cuando se utiliza <f:ajax>, sería en el caso de los comandos de componentes prefiero usar el action atributo para acciones comerciales. E. g. <h:commandButton action="#{bean.businessAction}"><f:ajax/></h:commandButton>.
    • Este <h:link value="Go to next page" outcome="nextpage" /> simplemente no funcionan en PrimeFaces. <h:outputLink obras
    • ese problema es causado en otros lugares y completamente ajena a la actual P&r: creo que la intención de publicar este comentario en otro post.
    • El problema que he mencionado lo que realmente sucede en el interior de un <p:treeTable>, en Liferay. Podría estar relacionado con eso. Gracias.
    • devolver un valor null de un método de acción pierde los parámetros de la petición. Podría por favor explicar cómo pueden ser mantenidos en estas circunstancias? Gracias!
    • Es probable que un misobservation. El mismo problema se produce cuando la devolución no nulo. La cabeza en el stackoverflow.com/q/17734230.
    • Yo había encontrado que también, pero que se quieran distinguir entre devolviendo null y el uso de vacío. El post se hace referencia fue para redireccionar a otra página. Si la acción que se necesita para volver a la misma página después de un error de validación, el cómo es que el mejor hecho en el fin de mantener los parámetros pero no llame a la PostConstruct método que en mi caso va a reiniciar todos los valores?

  2. 47

    Como BalusC indicado, el actionListener por defecto se traga excepciones, pero en JSF 2.0 hay un poco más de esto. Es decir, no sólo las golondrinas y los registros, pero en realidad publica la excepción.

    Esto sucede a través de una llamada como esta:

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

    El agente de escucha predeterminado para este evento es el ExceptionHandler que para Mojarra se establece en com.sun.faces.context.ExceptionHandlerImpl. Esta aplicación básicamente rethrow excepción alguna, salvo cuando se trata de un AbortProcessingException, que se registra. ActionListeners envoltura de la excepción que se produce por el código de cliente en un AbortProcessingException que explica por qué estas siempre se registran.

    Este ExceptionHandler puede ser reemplazado sin embargo en faces-config.xml con una implementación personalizada:

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

    En lugar de escuchar a nivel mundial, una sola bean también se puede escuchar a estos eventos. La siguiente es una prueba de concepto de esta:

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

    (nota, esto no es cómo uno se debe normalmente el código de los oyentes, esto es sólo para fines de demostración!)

    De llamar a este de un Facelet como este:

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

    Resultará en un error de la página que se muestra.

  3. 43

    ActionListener despiden a primera, con una opción para modificar la respuesta, antes de la Acción se llama y determina la ubicación de la página siguiente.

    Si usted tiene varios botones en la misma página que debería ir al mismo lugar pero hacer cosas ligeramente diferentes, puede utilizar la misma Acción para cada botón, pero el uso de diferentes ActionListener para manejar una funcionalidad ligeramente diferente.

    Aquí hay un enlace que describe la relación:

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

    • más uno, Las letras en negrita dice casi todo.
  4. 0

    TL;DR:

    La ActionListeners (puede haber varios) se ejecutan en el orden en que se registraron ANTES de la action

    Respuesta Larga:

    Un negocio action normalmente se invoca un EJB de servicio y si es necesario también se establece el resultado final y/o se desplaza a un punto de vista diferente
    si eso no es lo que usted está haciendo un actionListener es más apropiado decir, para cuando el usuario interactúa con los componentes, tales como h:commandButton o h:link que puede ser manejado por pasar el nombre del bean gestionado método en actionListener atributo de un Componente de interfaz de usuario o la implementación de un ActionListener interfaz y pasar la implementación nombre de la clase a actionListener atributo de un Componente de interfaz de usuario.

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea