Differenze tra azione e azioneListener

Qual è la differenza tra action e actionListener e quando dovrei usare action contro actionListener ?

ActionListener

Utilizzare actionListener se si desidera un hook prima che actionListener eseguita l’azione di business reale, ad esempio per registrarlo e / o per impostare una proprietà aggiuntiva (per ), e / o per avere accesso al componente che ha richiamato il azione (che è disponibile per argomento ActionEvent ). Quindi, puramente per preparare gli scopi prima che la vera azione commerciale venga invocata.

Il metodo actionListener ha per impostazione predefinita la seguente firma:

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

E dovrebbe essere dichiarato come segue, senza alcuna parentesi di metodo:

  

Nota che non puoi passare argomenti addizionali con EL 2.2. Tuttavia, è ansible sovrascrivere completamente l’argomento ActionEvent passando e specificando argomenti personalizzati. I seguenti esempi sono validi:

    
 public void methodWithoutArguments() {} public void methodWithOneArgument(Object arg1) {} public void methodWithTwoArguments(Object arg1, Object arg2) {} 

Notare l’importanza delle parentesi nell’espressione del metodo senza argomenti. Se fossero assenti, JSF si aspetterebbe comunque un metodo con argomento ActionEvent .

Se si utilizza EL 2.2+, è ansible dichiarare più metodi di listener di azioni tramite .

     
 public void actionListener1(ActionEvent event) {} public void actionListener2() {} public void actionListener3() {} 

Notare l’importanza delle parentesi nell’attributo di binding . Se fossero assenti, EL avrebbe gettato in modo confuso un javax.el.PropertyNotFoundException: Property 'actionListener1' not found on type com.example.Bean , perché l’attributo di javax.el.PropertyNotFoundException: Property 'actionListener1' not found on type com.example.Bean è interpretato come un’espressione di valore, non come un’espressione di metodo. L’aggiunta di parentesi in stile EL 2.2+ trasforma in modo trasparente un’espressione di valore in un’espressione di metodo. Vedi anche ao Perché sono in grado di associare a un metodo arbitrario se non è supportato da JSF?


azione

Utilizzare l’ action se si desidera eseguire un’azione commerciale e, se necessario, gestire la navigazione. Il metodo action può (quindi, non deve) restituire una String che verrà utilizzata come risultato del caso di navigazione (la vista di destinazione). Un valore restituito di null o void consentirà di tornare alla stessa pagina e mantenere vivo l’ambito di visualizzazione corrente. Un valore di ritorno di una stringa vuota o lo stesso ID vista tornerà anche alla stessa pagina, ma ricrea l’ambito della vista e quindi distruggerà tutti i bean con scope vista attualmente attivi e, se applicabile, li ricreerà.

Il metodo di action può essere qualsiasi MethodExpression valida, anche quelli che utilizzano argomenti EL 2.2 come di seguito:

  

Con questo metodo:

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

Nota che quando il tuo metodo di azione restituisce solamente una stringa, puoi anche specificare esattamente quella stringa nell’attributo action . Quindi, questo è totalmente impacciato:

  

Con questo metodo privo di senso che restituisce una stringa codificata:

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

Invece, metti semplicemente quella stringa hardcoded direttamente nell’attributo:

  

Si prega di notare che questo a sua volta indica un cattivo design: la navigazione tramite POST. Questo non è né utente né SEO amichevole. Tutto questo è spiegato in Quando dovrei usare h: outputLink invece di h: commandLink? e dovrebbe essere risolto come

  

Vedi anche Come navigare in JSF? Come rendere l’URL riflette la pagina corrente (e non quella precedente) .


f: ascoltatore di ajax

Dal momento che JSF 2.x esiste un terzo modo, .

    

Il metodo ajaxListener ha per impostazione predefinita la seguente firma:

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

In Mojarra, l’argomento AjaxBehaviorEvent è facoltativo, di seguito funziona come buono.

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

Ma in MyFaces, genererebbe un MethodNotFoundException . Qui sotto funziona in entrambe le implementazioni JSF quando si desidera omettere l’argomento.

    

Gli ascoltatori Ajax non sono veramente utili sui componenti di comando. Sono più utili sull’input e selezionare i componenti / . Nei componenti di comando, è sufficiente attenersi action e / o actionListener per chiarezza e codice di actionListener migliore. Inoltre, come actionListener , il f:ajax listener non supporta il ritorno di un risultato di navigazione.

    

Per spiegazioni sugli attributi di execute e render , vai a Understanding PrimeFaces process / update e JSF f: ajax esegue / restituisce attributi .


Ordine di invocazione

Gli actionListener vengono sempre richiamati prima action nello stesso ordine in cui sono stati dichiarati nella vista e collegati al componente. Il f:ajax listener viene sempre richiamato prima di ogni listener di azioni. Quindi, il seguente esempio:

       

Invocherà i metodi nel seguente ordine:

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

La gestione delle eccezioni

actionListener supporta un’eccezione speciale: AbortProcessingException . Se questa eccezione viene lanciata da un metodo actionListener , JSF salterà eventuali listener di azione rimanenti e il metodo di azione e procederà a rendere la risposta direttamente. Non vedrai una pagina di errore / eccezione, ma JSF lo registrerà. Questo sarà implicitamente fatto anche ogni volta che un’altra eccezione viene lanciata da un actionListener . Pertanto, se si intende bloccare la pagina in base a una pagina di errore come risultato di un’eccezione aziendale, è necessario eseguire il lavoro nel metodo di action .

Se l’unica ragione per usare un actionListener è di avere un metodo void che ritorna alla stessa pagina, allora quello è cattivo. I metodi di action possono anche restituire perfettamente void , al contrario di ciò che alcuni IDE consentono di credere tramite la convalida EL. Si noti che gli esempi di vetrine di PrimeFaces sono actionListener di questo tipo di actionListener su tutto il posto. Questo è davvero sbagliato. Non usare questo come scusa per farlo anche tu.

In richieste Ajax, tuttavia, è necessario un gestore di eccezioni speciale. Questo indipendentemente dal fatto che si usi l’attributo listener di o meno. Per spiegazioni e un esempio, vai alla gestione delle eccezioni nelle richieste Ajax JSF .

Come indicato da BalusC, actionListener di default actionListener eccezioni, ma in JSF 2.0 c’è un po ‘di più in questo. Vale a dire, non solo ingoia e registra, ma in realtà pubblica l’eccezione.

Questo succede attraverso una chiamata come questa:

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

Il listener predefinito per questo evento è ExceptionHandler che per Mojarra è impostato su com.sun.faces.context.ExceptionHandlerImpl . Questa implementazione ridurrà fondamentalmente qualsiasi eccezione, tranne quando si tratta di AbortProcessingException, che viene registrata. ActionListeners racchiude l’eccezione generata dal codice client in tale AbortProcessingException che spiega il motivo per cui vengono sempre registrati.

Questo ExceptionHandler può essere sostituito tuttavia in faces-config.xml con un’implementazione personalizzata:

  com.foo.myExceptionHandler  

Invece di ascoltare globalmente, un singolo bean può anche ascoltare questi eventi. Quanto segue è una prova del concetto di questo:

 @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, questo non è il modo in cui normalmente si dovrebbero codificare gli ascoltatori, questo è solo a scopo dimostrativo!)

Chiamando questo da un Facelet come questo:

        

Comporterà la visualizzazione di una pagina di errore.

Prima viene lanciato ActionListener, con un’opzione per modificare la risposta, prima che Action venga chiamata e determina la posizione della pagina successiva.

Se nella stessa pagina ci sono più pulsanti che dovrebbero andare nello stesso posto ma fare cose leggermente diverse, è ansible utilizzare la stessa azione per ciascun pulsante, ma utilizzare un ActionListener diverso per gestire funzionalità leggermente diverse.

Ecco un link che descrive la relazione:

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