Notei que existem diferentes escopos de bean como:
@RequestScoped
@ViewScoped
@FlowScoped
@SessionScoped
@ApplicationScoped
Qual é o objetivo de cada um? Como escolho um escopo adequado para o meu bean?
Notei que existem diferentes escopos de bean como:
@RequestScoped
@ViewScoped
@FlowScoped
@SessionScoped
@ApplicationScoped
Qual é o objetivo de cada um? Como escolho um escopo adequado para o meu bean?
Respostas:
Representa o escopo (a vida útil) do bean. Isso é mais fácil de entender se você estiver familiarizado com o trabalho "oculto" de um aplicativo da web de servlet básico: Como os servlets funcionam? Instanciação, sessões, variáveis compartilhadas e multithreading .
@Request/View/Flow/Session/ApplicationScoped
Um @RequestScoped
bean dura o tempo que um único ciclo de solicitação-resposta HTTP (observe que uma solicitação Ajax também conta como uma única solicitação HTTP). Um @ViewScoped
bean permanece enquanto você está interagindo com a mesma visualização JSF por postbacks que chamam métodos de ação retornando null
/ void
sem nenhuma navegação / redirecionamento. Um @FlowScoped
bean dura enquanto você estiver navegando pela coleção especificada de visualizações registradas no arquivo de configuração do fluxo. Um @SessionScoped
bean permanece enquanto a sessão HTTP estabelecida. Um @ApplicationScoped
bean dura enquanto o aplicativo da web é executado. Observe que o CDI @Model
é basicamente um estereótipo para @Named @RequestScoped
, então as mesmas regras se aplicam.
Qual escopo escolher depende apenas dos dados (o estado) que o bean mantém e representa. Use @RequestScoped
para formulários / apresentações simples e não-ajax. Use @ViewScoped
para visualizações dinâmicas ativadas por ajax (validação, renderização, caixas de diálogo, etc.). Use @FlowScoped
para o padrão "assistente" ("questionário") de coleta de dados de entrada espalhados por várias páginas. Use @SessionScoped
para dados específicos do cliente, como usuário conectado e preferências do usuário (idioma etc.). Use @ApplicationScoped
para dados / constantes abrangentes do aplicativo, como listas suspensas iguais para todos, ou beans gerenciados sem nenhuma variável de instância e possuindo apenas métodos.
O abuso de um @ApplicationScoped
bean para dados com escopo de sessão / exibição / solicitação faria com que ele fosse compartilhado entre todos os usuários, para que qualquer pessoa possa ver os dados um do outro, o que está errado. O abuso de um @SessionScoped
bean para dados com escopo de exibição / solicitação faria com que fosse compartilhado entre todas as guias / janelas em uma única sessão do navegador, para que o usuário final possa experimentar inconsistências ao interagir com todas as visualizações após alternar entre guias, o que é ruim para a experiência do usuário. O abuso de um @RequestScoped
bean para dados com escopo de exibição faria com que os dados com escopo fossem reinicializados para o padrão em cada postagem (ajax), causando possivelmente formulários que não funcionam ( veja também os pontos 4 e 5 aqui ). Abusar de um @ViewScoped
bean para dados com escopo de solicitação, sessão ou aplicativo e abusar de um@SessionScoped
O bean para dados com escopo do aplicativo não afeta o cliente, mas ocupa desnecessariamente a memória do servidor e é ineficiente.
Observe que o escopo não deve ser escolhido com base nas implicações de desempenho, a menos que você realmente tenha pouco espaço na memória e queira ficar completamente sem estado; você precisaria usar exclusivamente @RequestScoped
beans e mexer com parâmetros de solicitação para manter o estado do cliente. Observe também que quando você tem uma única página JSF com dados com escopo diferente, é perfeitamente válido colocá-los em beans de backup separados em um escopo que corresponda ao escopo dos dados. Os beans podem apenas acessar um ao outro via @ManagedProperty
no caso de beans gerenciados JSF ou @Inject
no caso de beans gerenciados CDI.
@CustomScoped/NoneScoped/Dependent
Isso não é mencionado na sua pergunta, mas o JSF (legado) também suporta @CustomScoped
e @NoneScoped
, que raramente são usados no mundo real. Ele @CustomScoped
deve se referir a uma Map<K, Bean>
implementação customizada em um escopo mais amplo que foi substituído Map#put()
e / ou Map#get()
para ter um controle mais refinado da criação e / ou destruição do bean.
O JSF @NoneScoped
e o CDI @Dependent
vivem basicamente enquanto uma única avaliação EL no bean. Imagine um formulário de login com dois campos de entrada referentes a uma propriedade de bean e um botão de comando referente a uma ação de bean, portanto, com um total de três expressões EL, e efetivamente três instâncias serão criadas. Um com o nome de usuário definido, um com a senha definida e um no qual a ação é invocada. Você normalmente deseja usar esse escopo apenas em beans que devem permanecer enquanto o bean estiver sendo injetado. Portanto, se um @NoneScoped
ou @Dependent
for injetado em um @SessionScoped
, ele viverá tanto quanto o @SessionScoped
feijão.
Por último, o JSF também suporta o escopo do flash. É apoiado por um cookie de curta duração, associado a uma entrada de dados no escopo da sessão. Antes do redirecionamento, um cookie será definido na resposta HTTP com um valor associado exclusivamente à entrada de dados no escopo da sessão. Após o redirecionamento, a presença do cookie do escopo flash será verificada e a entrada de dados associada ao cookie será removida do escopo da sessão e colocada no escopo da solicitação redirecionada. Finalmente, o cookie será removido da resposta HTTP. Dessa forma, a solicitação redirecionada tem acesso aos dados com escopo definido, que foram preparados na solicitação inicial.
Na verdade, isso não está disponível como um escopo de bean gerenciado, ou seja, não existe @FlashScoped
. O escopo do flash está disponível apenas como um mapa ExternalContext#getFlash()
nos beans gerenciados e #{flash}
no EL.
@FlowScoped
(não é necessário iniciar / parar manualmente).
ViewAccesscoped
eWindowScoped
ViewScoped
bean no MyFaces 2.2. Atualmente, estou enfrentando um problema com o ViewScoped
bean e o Ajax, que publiquei aqui . No MyFaces JIRA, também há uma discussão sobre esse tópico.
@RequestScoped
@SessionScoped
@ApplicationScoped
@ConversationScoped
por que os escopos que você descreve são diferentes?
Desde o JSF 2.3, todos os escopos de bean definidos no pacote javax.faces.bean
package foram descontinuados para alinhar os escopos ao CDI. Além disso, eles são aplicáveis apenas se seu bean estiver usando @ManagedBean
anotação. Se você estiver usando as versões JSF abaixo de 2.3, consulte a resposta herdada no final.
No JSF 2.3, aqui estão os escopos que podem ser usados no JSF Backing Beans:
1@javax.enterprise.context.ApplicationScoped
.: O escopo do aplicativo persiste por toda a duração do aplicativo da web. Esse escopo é compartilhado entre todas as solicitações e todas as sessões. Isso é útil quando você possui dados para todo o aplicativo.
2@javax.enterprise.context.SessionScoped
.: O escopo da sessão persiste desde o momento em que uma sessão é estabelecida até o término da sessão. O contexto da sessão é compartilhado entre todas as solicitações que ocorrem na mesma sessão HTTP. Isso é útil quando você não salva dados de um cliente específico para uma sessão específica.
3@javax.enterprise.context.ConversationScoped
.: O escopo da conversa persiste como o log que o bean vive. O escopo fornece 2 métodos: Conversation.begin()
e Conversation.end()
. Esses métodos devem ser chamados explicitamente, para iniciar ou finalizar a vida útil de um bean.
4@javax.enterprise.context.RequestScoped
.: O escopo da solicitação é de curta duração. Inicia quando uma solicitação HTTP é enviada e termina após a resposta ser enviada de volta ao cliente. Se você colocar um bean gerenciado no escopo da solicitação, uma nova instância será criada com cada solicitação. Vale a pena considerar o escopo da solicitação se você estiver preocupado com o custo do armazenamento do escopo da sessão.
5@javax.faces.flow.FlowScoped
.: O escopo do fluxo persiste enquanto o fluxo permanecer. Um fluxo pode ser definido como um conjunto contido de páginas (ou visualizações) que definem uma unidade de trabalho. O escopo definido como fluxo está ativo enquanto o usuário navega no fluxo.
6@javax.faces.view.ViewScoped
.: Um escopo do bean no modo de exibição persiste enquanto a mesma página JSF é exibida novamente. Assim que o usuário navega para uma página diferente, o bean fica fora do escopo.
A resposta legada a seguir aplica a versão JSF anterior à 2.3
No JSF 2.x, existem 4 escopos de bean:
- @SessionScoped
- @RequestScoped
- @ApplicationScoped
- @ViewScoped
Escopo da sessão: o escopo da sessão persiste desde o momento em que uma sessão é estabelecida até o término da sessão. Uma sessão termina se o aplicativo Web chamar o método invalidate no objeto HttpSession ou se o tempo limite for excedido.
RequestScope: o escopo da solicitação é de curta duração. Inicia quando uma solicitação HTTP é enviada e termina após a resposta ser enviada de volta ao cliente. Se você colocar um bean gerenciado no escopo da solicitação, uma nova instância será criada com cada solicitação. Vale a pena considerar o escopo da solicitação se você estiver preocupado com o custo do armazenamento do escopo da sessão.
ApplicationScope: o escopo do aplicativo persiste por toda a duração do aplicativo da web. Esse escopo é compartilhado entre todas as solicitações e todas as sessões. Você coloca beans gerenciados no escopo do aplicativo se um único bean deve ser compartilhado entre todas as instâncias de um aplicativo Web. O bean é construído quando é solicitado pela primeira vez por qualquer usuário do aplicativo e permanece ativo até que o aplicativo da Web seja removido do servidor de aplicativos.
ViewScope: o escopo da visualização foi adicionado no JSF 2.0. Um bean no escopo de exibição persiste enquanto a mesma página JSF é exibida novamente. (A especificação JSF usa o termo view para uma página JSF.) Assim que o usuário navega para uma página diferente, o bean fica fora do escopo.
Escolha o escopo com base em seus requisitos.
Fonte: Core Java Server Faces 3rd Edition por David Geary e Cay Horstmann [Página no. 51 - 54]
invalidate()
método ou método inválido?
FacesContext.getCurrentInstance().getExternalContext().invalidateSession();
ser invocado no seu "logout bean" é o que ele quer dizer.