Ho notato che esistono diversi ambiti bean come:
@RequestScoped
@ViewScoped
@FlowScoped
@SessionScoped
@ApplicationScoped
Qual è lo scopo di ciascuno? Come faccio a scegliere un ambito adeguato per il mio bean?
Ho notato che esistono diversi ambiti bean come:
@RequestScoped
@ViewScoped
@FlowScoped
@SessionScoped
@ApplicationScoped
Qual è lo scopo di ciascuno? Come faccio a scegliere un ambito adeguato per il mio bean?
Risposte:
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 @RequestScoped
bean dura fino a quando un singolo ciclo di richiesta-risposta HTTP (si noti che una richiesta Ajax conta anche come singola richiesta HTTP). Un @ViewScoped
bean rimane attivo finché interagisci con la stessa vista JSF tramite postback che richiamano i metodi di azione di ritorno null
/ void
senza navigazione / reindirizzamento. Un @FlowScoped
bean rimane attivo finché si naviga attraverso la raccolta di viste specificata registrata nel file di configurazione del flusso. Un @SessionScoped
bean rimane attivo fino alla sessione HTTP stabilita. Un @ApplicationScoped
bean 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 @RequestScoped
per moduli / presentazioni semplici e non ajax. Utilizzare @ViewScoped
per visualizzazioni dinamiche abilitate per ajax (convalida, rendering, finestre di dialogo basate su ajax, ecc.). Utilizzare @FlowScoped
per il modello "procedura guidata" ("questionario") di raccolta dei dati di input distribuiti su più pagine. Utilizzare @SessionScoped
per dati specifici del cliente, come l'utente che ha effettuato l'accesso e le preferenze dell'utente (lingua, ecc.). Utilizzare @ApplicationScoped
per 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 @ApplicationScoped
bean 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 @SessionScoped
bean 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 @RequestScoped
bean 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 @ViewScoped
bean 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 @RequestScoped
bean 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 @ManagedProperty
nel caso di bean gestiti JSF o @Inject
nel caso di bean gestiti CDI.
@CustomScoped/NoneScoped/Dependent
Non è menzionato nella tua domanda, ma JSF (legacy) supporta anche @CustomScoped
e @NoneScoped
, che sono usati raramente nel mondo reale. La @CustomScoped
deve 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 @NoneScoped
e il CDI @Dependent
praticamente 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 @NoneScoped
o @Dependent
viene iniettato in a @SessionScoped
, vivrà fino a quando il @SessionScoped
bean.
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.
@FlowScoped
(non è necessario avviarlo / arrestarlo manualmente).
ViewAccesscoped
eWindowScoped
ViewScoped
bean in MyFaces 2.2. Attualmente sto affrontando un problema con ViewScoped
bean e Ajax, che ho pubblicato qui . In MyFaces JIRA, c'è anche una discussione su questo argomento.
@RequestScoped
@SessionScoped
@ApplicationScoped
@ConversationScoped
perché gli ambiti che descrivi sono diversi?
Da JSF 2.3 tutti gli ambiti bean definiti nel pacchetto del javax.faces.bean
pacchetto sono stati deprecati per allineare gli ambiti con CDI. Inoltre, sono applicabili solo se il bean utilizza l' @ManagedBean
annotazione. 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]
invalidate()
non valido sull'oggetto HttpSession": metodo o metodo non valido?
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
essere invocato nel tuo "bean di logout" è ciò che intende.