¿Cuál es la diferencia entre actiony actionListener, y cuándo debo usar actionversus actionListener?
fuente
¿Cuál es la diferencia entre actiony actionListener, y cuándo debo usar actionversus actionListener?
Úselo actionListenersi desea tener un enlace antes de que se ejecute la acción comercial real, por ejemplo, para iniciar sesión y / o para establecer una propiedad adicional (por <f:setPropertyActionListener>), y / o tener acceso al componente que invocó la acción (que está disponible por ActionEventargumento). Por lo tanto, solo con fines de preparación antes de que se invoque la acción comercial real.
El actionListenermétodo tiene por defecto la siguiente firma:
import javax.faces.event.ActionEvent;
// ...
public void actionListener(ActionEvent event) {
// ...
}
Y se supone que debe declararse de la siguiente manera, sin ningún paréntesis de método:
<h:commandXxx ... actionListener="#{bean.actionListener}" />
Tenga en cuenta que no puede pasar argumentos adicionales por EL 2.2. Sin embargo, puede anular el ActionEventargumento por completo pasando y especificando argumentos personalizados. Los siguientes ejemplos son válidos:
<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) {}
Tenga en cuenta la importancia de los paréntesis en la expresión del método sin argumentos. Si estuvieran ausentes, JSF aún esperaría un método con ActionEventargumento.
Si está en EL 2.2+, puede declarar varios métodos de escucha de acción 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() {}
Tenga en cuenta la importancia de los paréntesis en el bindingatributo. Si estuvieran ausentes, EL arrojaría confusamente a javax.el.PropertyNotFoundException: Property 'actionListener1' not found on type com.example.Bean, porque el bindingatributo se interpreta por defecto como una expresión de valor, no como una expresión de método. Agregar paréntesis de estilo EL 2.2+ convierte transparentemente una expresión de valor en una expresión de método. Consulte también ao ¿Por qué puedo vincular <f: actionListener> a un método arbitrario si JSF no lo admite?
Úselo actionsi desea ejecutar una acción comercial y, si es necesario, manejar la navegación. El actionmétodo puede (por lo tanto, no debe) devolver un Stringque se utilizará como resultado del caso de navegación (la vista de destino). Un valor de retorno de nullo voidle permitirá volver a la misma página y mantener vivo el alcance de la vista actual. Un valor de retorno de una cadena vacía o la misma ID de vista también volverá a la misma página, pero recreará el alcance de la vista y, por lo tanto, destruirá cualquier bean de ámbito de vista actualmente activo y, si corresponde, vuelva a crearlos.
El actionmétodo puede ser válido MethodExpression, también los que usan argumentos EL 2.2 como los siguientes:
<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 solo devuelve una cadena, también puede especificar exactamente esa cadena en el actionatributo. Por lo tanto, esto es totalmente torpe:
<h:commandLink value="Go to next page" action="#{bean.goToNextpage}" />
Con este método sin sentido que devuelve una cadena codificada:
public String goToNextpage() {
return "nextpage";
}
En cambio, solo ponga esa cadena codificada directamente en el atributo:
<h:commandLink value="Go to next page" action="nextpage" />
Tenga en cuenta que esto a su vez indica un mal diseño: navegar por POST. Esto no es fácil de usar ni SEO. Todo esto se explica en ¿ Cuándo debo usar h: outputLink en lugar de h: commandLink? y se supone que debe resolverse como
<h:link value="Go to next page" outcome="nextpage" />
Consulte también ¿Cómo navegar en JSF? Cómo hacer que la URL refleje la página actual (y no la anterior) .
Desde JSF 2.x hay una tercera vía, la <f:ajax listener>.
<h:commandXxx ...>
<f:ajax listener="#{bean.ajaxListener}" />
</h:commandXxx>
El ajaxListenermétodo tiene por defecto la siguiente firma:
import javax.faces.event.AjaxBehaviorEvent;
// ...
public void ajaxListener(AjaxBehaviorEvent event) {
// ...
}
En Mojarra, el AjaxBehaviorEventargumento es opcional, a continuación funciona igual de bien.
public void ajaxListener() {
// ...
}
Pero en MyFaces, arrojaría un MethodNotFoundException. A continuación funciona en ambas implementaciones JSF cuando desea omitir el argumento.
<h:commandXxx ...>
<f:ajax execute="@form" listener="#{bean.ajaxListener()}" render="@form" />
</h:commandXxx>
Los oyentes Ajax no son realmente útiles en los componentes del comando. Son más útiles en la entrada y seleccionan componentes <h:inputXxx>/ <h:selectXxx>. En los componentes de comando, simplemente manténgase actiony / o actionListenerpara mayor claridad y mejor código de autodocumentación. Además, al igual que actionListener, f:ajax listenerno admite la devolución de un resultado de navegación.
<h:commandXxx ... action="#{bean.action}">
<f:ajax execute="@form" render="@form" />
</h:commandXxx>
Para obtener explicaciones executey renderatributos, diríjase a Comprensión del proceso / actualización de PrimeFaces y JSF f: ajax ejecutar / renderizar atributos .
Los actionListeners siempre se invocan antes de la actionen el mismo orden en que se han declarado en la vista y se unen al componente. El f:ajax listenersiempre se invoca antes de cualquier escucha de acción. Entonces, 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>
Invocará los métodos en el siguiente orden:
Bean#ajaxListener()Bean#actionListener()ActionListenerType#processAction()Bean#actionListenerBinding()Bean#setProperty()Bean#action()El actionListeneradmite una excepción especial: AbortProcessingException. Si se lanza esta excepción desde un actionListenermétodo, JSF omitirá cualquier escucha de acción restante y el método de acción y procederá a procesar la respuesta directamente. No verá una página de error / excepción, sin embargo, JSF lo registrará. Esto también se hará implícitamente cuando se produzca cualquier otra excepción desde unactionListener . Entonces, si tiene la intención de bloquear la página por una página de error como resultado de una excepción comercial, entonces definitivamente debe realizar el trabajo en el actionmétodo.
Si la única razón para usar un actionListeneres que un voidmétodo regrese a la misma página, entonces ese es uno malo. Los actionmétodos también pueden regresar perfectamente void, al contrario de lo que algunos IDEs le permiten creer a través de la validación EL. Tenga en cuenta que los ejemplos de escaparate de PrimeFaces están llenos de este tipo de actionListeners en todo lugar. Esto de hecho está mal. No uses esto como una excusa para hacerlo tú mismo.
En las solicitudes ajax, sin embargo, se necesita un controlador de excepción especial. Esto es independientemente de si usa el listeneratributo de <f:ajax>o no. Para obtener una explicación y un ejemplo, diríjase a Manejo de excepciones en solicitudes JSF ajax .
actionListener, pero eso aún no es una buena excusa para abusaractionListenerde las acciones comerciales .actioncorresponde con eso.actionListeneres para cosas secundarias. Solo quería aclarar que las excepciones deactionListeners pueden propagarse si es necesario;)actionListeneratributo y también debe serlopublic. ElprocessActionnombre solo es obligatorio cuando lo usa<f:actionListener type>, simplemente porque el tipo tiene que implementar unaActionListenerinterfaz que tenga exactamente ese nombre de métodoprocessActiondefinido.<f:ajax>, en el caso de componentes de comando preferiría usar elactionatributo para acciones comerciales. Por ej<h:commandButton action="#{bean.businessAction}"><f:ajax/></h:commandButton>.Como BalusC indicó,
actionListenerpor defecto se traga excepciones, pero en JSF 2.0 hay un poco más de esto. Es decir, no solo se traga y registra, sino que en realidad publica la excepción.Esto sucede a través de una llamada como esta:
El oyente predeterminado para este evento es el
ExceptionHandlerque para Mojarra está configurado encom.sun.faces.context.ExceptionHandlerImpl. Esta implementación básicamente volverá a generar cualquier excepción, excepto cuando se trata de una excepción AbortProcessingException, que se registra. Los ActionListeners envuelven la excepción que arroja el código del cliente en una AbortProcessingException que explica por qué siempre se registran.Sin
ExceptionHandlerembargo, esto se puede reemplazar en faces-config.xml con una implementación personalizada:En lugar de escuchar globalmente, un solo bean también puede escuchar estos eventos. Lo siguiente es una prueba de concepto de esto:
(tenga en cuenta que no es así como se deben codificar normalmente los oyentes, ¡esto es solo para fines de demostración!)
Llamando a esto desde un Facelet como este:
Resultará en una página de error que se muestra.
fuente
ActionListener se dispara primero, con una opción para modificar la respuesta, antes de que se llame a Action y determine la ubicación de la página siguiente.
Si tiene varios botones en la misma página que deberían ir al mismo lugar pero hacer cosas ligeramente diferentes, puede usar la misma Acción para cada botón, pero use un ActionListener diferente para manejar funcionalidades ligeramente diferentes.
Aquí hay un enlace que describe la relación:
http://www.java-samples.com/showtutorial.php?tutorialid=605
fuente
TL; DR :
Los
ActionListeners (pueden ser múltiples) se ejecutan en el orden en que se registraron ANTES deactionRespuesta larga :
Una empresa
actiongeneralmente invoca un servicio EJB y, si es necesario, también establece el resultado final y / o navega a una vista diferente si eso no es lo que está haciendo yactionListeneres más apropiado, es decir, cuando el usuario interactúa con los componentes, comoh:commandButtonoh:linkpueden se maneja pasando el nombre del método de bean administrado en elactionListeneratributo de un Componente UI o para implementar unaActionListenerinterfaz y pasar el nombre de la clase de implementación alactionListeneratributo de un Componente UI.fuente