Come scegliere l'ambito bean giusto?


Risposte:


485

introduzione

Rappresenta l'ambito (la durata) del bean. Questo è più facile da capire se si ha familiarità con il funzionamento "sotto le coperte" di un'applicazione Web servlet di base: come funzionano i servlet? Istantanea, sessioni, variabili condivise e multithreading .


@Request/View/Flow/Session/ApplicationScoped

Un @RequestScopedbean dura fino a quando un singolo ciclo di richiesta-risposta HTTP (si noti che una richiesta Ajax conta anche come singola richiesta HTTP). Un @ViewScopedbean rimane attivo finché interagisci con la stessa vista JSF tramite postback che richiamano i metodi di azione di ritorno null/ voidsenza navigazione / reindirizzamento. Un @FlowScopedbean rimane attivo finché si naviga attraverso la raccolta di viste specificata registrata nel file di configurazione del flusso. Un @SessionScopedbean rimane attivo fino alla sessione HTTP stabilita. Un @ApplicationScopedbean rimane attivo finché l'applicazione Web è in esecuzione. Si noti che il CDI @Modelè sostanzialmente uno stereotipo per @Named @RequestScoped, quindi si applicano le stesse regole.

L'ambito da scegliere dipende esclusivamente dai dati (lo stato) contenuti e rappresentati dal bean. Utilizzare @RequestScopedper moduli / presentazioni semplici e non ajax. Utilizzare @ViewScopedper visualizzazioni dinamiche abilitate per ajax (convalida, rendering, finestre di dialogo basate su ajax, ecc.). Utilizzare @FlowScopedper il modello "procedura guidata" ("questionario") di raccolta dei dati di input distribuiti su più pagine. Utilizzare @SessionScopedper dati specifici del cliente, come l'utente che ha effettuato l'accesso e le preferenze dell'utente (lingua, ecc.). Utilizzare @ApplicationScopedper dati / costanti a livello di applicazione, come elenchi a discesa che sono uguali per tutti o bean gestiti senza variabili di istanza e con solo metodi.

L'abuso di un @ApplicationScopedbean per i dati con ambito sessione / vista / richiesta ne farebbe la condivisione tra tutti gli utenti, in modo che chiunque possa vedere i dati degli altri, il che è semplicemente sbagliato. L'abuso di un @SessionScopedbean per la visualizzazione / richiesta di dati con ambito renderebbe la condivisione tra tutte le schede / finestre in una singola sessione del browser, pertanto l'utente finale potrebbe riscontrare incongruenze durante l'interazione con ogni vista dopo il passaggio da una scheda all'altra, il che è negativo per l'esperienza dell'utente. L'abuso di un @RequestScopedbean per visualizzare i dati con ambito di visualizzazione renderebbe nuovamente inizializzati i dati con ambito di visualizzazione su ogni singolo postback (ajax), causando probabilmente moduli non funzionanti ( vedere anche i punti 4 e 5 qui ). Abuso di un @ViewScopedbean per richiesta, sessione o dati con ambito applicativo e abuso a@SessionScoped il bean per i dati nell'ambito dell'applicazione non influisce sul client, ma occupa inutilmente la memoria del server ed è chiaramente inefficiente.

Si noti che l'ambito non dovrebbe essere scelto in base alle implicazioni delle prestazioni, a meno che non si disponga davvero di un footprint di memoria ridotto e si desideri andare completamente senza stato; dovresti usare esclusivamente @RequestScopedbean e giocherellare con i parametri di richiesta per mantenere lo stato del client. Si noti inoltre che quando si dispone di una singola pagina JSF con dati con ambito diverso, è perfettamente valido inserirli in bean di supporto separati in un ambito corrispondente all'ambito dei dati. I bean possono accedervi semplicemente @ManagedPropertynel caso di bean gestiti JSF o @Injectnel caso di bean gestiti CDI.

Guarda anche:


@CustomScoped/NoneScoped/Dependent

Non è menzionato nella tua domanda, ma JSF (legacy) supporta anche @CustomScopede @NoneScoped, che sono usati raramente nel mondo reale. La @CustomScopeddeve fare riferimento una consuetudine Map<K, Bean>implementazione in qualche ambito più vasto, che ha ignorato Map#put()e / o Map#get()al fine di avere più controllo a grana fine sulla creazione di fagioli e / o distruggere.

Il JSF @NoneScopede il CDI @Dependentpraticamente durano fino a quando una singola valutazione EL sul bean. Immagina un modulo di login con due campi di input che fanno riferimento a una proprietà bean e un pulsante di comando che fa riferimento a un'azione bean, quindi con in totale tre espressioni EL, quindi verranno effettivamente create tre istanze. Uno con il nome utente impostato, uno con la password impostata e uno su cui viene invocata l'azione. Normalmente si desidera utilizzare questo ambito solo su bean che dovrebbero vivere fino a quando il bean in cui viene iniettato. Quindi se a @NoneScopedo @Dependentviene iniettato in a @SessionScoped, vivrà fino a quando il @SessionScopedbean.

Guarda anche:


Ambito Flash

Come ultimo, JSF supporta anche l'ambito flash. È supportato da un cookie di breve durata associato a una voce di dati nell'ambito della sessione. Prima del reindirizzamento, un cookie verrà impostato sulla risposta HTTP con un valore associato in modo univoco alla voce di dati nell'ambito della sessione. Dopo il reindirizzamento, verrà verificata la presenza del cookie dell'ambito flash e l'inserimento dei dati associato al cookie verrà rimosso dall'ambito della sessione e inserito nell'ambito della richiesta della richiesta reindirizzata. Alla fine il cookie verrà rimosso dalla risposta HTTP. In questo modo la richiesta reindirizzata ha accesso ai dati con ambito di richiesta che sono stati preparati nella richiesta iniziale.

Questo in realtà non è disponibile come ambito bean gestito, ovvero non esiste @FlashScoped. L'ambito flash è disponibile solo come mappa tramite ExternalContext#getFlash()in bean gestiti e #{flash}in EL.

Guarda anche:


4
Penso che un riferimento alla tua risposta alla domanda " Come e quando un bean di ambito di visualizzazione viene distrutto in JSF? " È pertinente qui.
Lii,

3
@Cold: questo è un vecchio ambito CDI e in JSF 2.2 sostituito con @FlowScoped(non è necessario avviarlo / arrestarlo manualmente).
BalusC,

1
E DeltaSpike ha inoltre ViewAccesscopedeWindowScoped
Kukeltje il

@BalusC, penso che ci sia un problema, con ViewScopedbean in MyFaces 2.2. Attualmente sto affrontando un problema con ViewScopedbean e Ajax, che ho pubblicato qui . In MyFaces JIRA, c'è anche una discussione su questo argomento.
Tapas Bose,

CDI definisce quattro ambiti incorporati: @RequestScoped @SessionScoped @ApplicationScoped @ConversationScoped perché gli ambiti che descrivi sono diversi?
Hosein Aqajani,

122

Da JSF 2.3 tutti gli ambiti bean definiti nel pacchetto del javax.faces.beanpacchetto sono stati deprecati per allineare gli ambiti con CDI. Inoltre, sono applicabili solo se il bean utilizza l' @ManagedBeanannotazione. Se si utilizzano versioni JSF inferiori alla 2.3, consultare la risposta precedente alla fine.


Da JSF 2.3 qui ci sono gli ambiti che possono essere utilizzati su fagioli di supporto JSF:

1@javax.enterprise.context.ApplicationScoped .: l'ambito dell'applicazione persiste per l'intera durata dell'applicazione Web. Tale ambito è condiviso tra tutte le richieste e tutte le sessioni. Ciò è utile quando si dispone di dati per l'intera applicazione.

2@javax.enterprise.context.SessionScoped .: L'ambito della sessione persiste dal momento in cui viene stabilita una sessione fino al termine della sessione. Il contesto della sessione è condiviso tra tutte le richieste che si verificano nella stessa sessione HTTP. Ciò è utile quando non si desidera salvare i dati per un client specifico per una determinata sessione.

3@javax.enterprise.context.ConversationScoped .: l'ambito della conversazione persiste come log come il bean vive. L'ambito offre 2 metodi: Conversation.begin()e Conversation.end(). Questi metodi dovrebbero essere chiamati in modo esplicito, per iniziare o terminare la vita di un bean.

4@javax.enterprise.context.RequestScoped .: l'ambito della richiesta è di breve durata. Inizia quando viene inoltrata una richiesta HTTP e termina dopo che la risposta è stata inviata al client. Se si inserisce un bean gestito nell'ambito della richiesta, viene creata una nuova istanza con ogni richiesta. Vale la pena considerare l'ambito della richiesta se si è preoccupati del costo dell'archiviazione dell'ambito della sessione.

5@javax.faces.flow.FlowScoped .: l'ambito Flow persiste finché il flusso rimane attivo. Un flusso può essere definito come un insieme contenuto di pagine (o viste) che definiscono un'unità di lavoro. Il flusso con ambito stato è attivo fintanto che l'utente naviga con nel flusso.

6@javax.faces.view.ViewScoped .: un bean in ambito view persiste mentre viene visualizzata nuovamente la stessa pagina JSF. Non appena l'utente passa a una pagina diversa, il bean non rientra nell'ambito.


La seguente risposta legacy si applica alla versione JSF precedente alla 2.3

A partire da JSF 2.x ci sono 4 Bean Scopes:

  • @SessionScoped
  • @RequestScoped
  • @ApplicationScoped
  • @ViewScoped

Ambito della sessione: l'ambito della sessione persiste dal momento in cui viene stabilita una sessione fino al termine della sessione. Una sessione termina se l'applicazione Web richiama il metodo invalidato sull'oggetto HttpSession o se scade.

RequestScope: l'ambito della richiesta è di breve durata. Inizia quando viene inoltrata una richiesta HTTP e termina dopo che la risposta è stata inviata al client. Se si inserisce un bean gestito nell'ambito della richiesta, viene creata una nuova istanza con ogni richiesta. Vale la pena considerare l'ambito della richiesta se si è preoccupati del costo dell'archiviazione dell'ambito della sessione.

ApplicationScope: l'ambito dell'applicazione persiste per l'intera durata dell'applicazione Web. Tale ambito è condiviso tra tutte le richieste e tutte le sessioni. I bean gestiti vengono inseriti nell'ambito dell'applicazione se un singolo bean deve essere condiviso tra tutte le istanze di un'applicazione Web. Il bean viene creato quando viene richiesto per la prima volta da qualsiasi utente dell'applicazione e rimane attivo fino a quando l'applicazione Web non viene rimossa dal server delle applicazioni.

ViewScope: View scope è stato aggiunto in JSF 2.0. Un bean in ambito view persiste mentre viene visualizzata nuovamente la stessa pagina JSF. (La specifica JSF utilizza il termine view per una pagina JSF.) Non appena l'utente passa a una pagina diversa, il bean esce dall'ambito.

Scegli l'ambito in base alle tue esigenze.

Fonte: Core Java Server Faces 3a edizione di David Geary e Cay Horstmann [Pagina n. 51 - 54] inserisci qui la descrizione dell'immagine


Potresti chiarire, cosa intendi con "il metodo invalidate()non valido sull'oggetto HttpSession": metodo o metodo non valido?
Alexander Pozdneev,

1
Un po 'vecchio e forse in ritardo per la risposta, ma per chiarirlo: FacesContext.getCurrentInstance().getExternalContext().invalidateSession();essere invocato nel tuo "bean di logout" è ciò che intende.
Roland,

1
è diventata una risposta legacy, al momento ci sono 8 ambiti
Ewoks

@KishorPrakash: un po 'è ora 6 mesi fa. ;-)
Kukeltje,

@Kukeltje: scusa, ci sono.
Kishor Prakash,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.