Por que o JSF precisa salvar o estado dos componentes da IU no servidor?
Porque o HTTP não tem estado e o JSF tem estado. A árvore de componentes JSF está sujeita a alterações dinâmicas (programáticas). O JSF simplesmente precisa saber o estado exato em que estava quando o formulário foi exibido para o usuário final, para que possa processar com êxito todo o ciclo de vida do JSF com base nas informações fornecidas pela árvore de componentes JSF original quando o formulário foi enviado de volta para o servidor. A árvore de componentes fornece informações sobre os nomes dos parâmetros de solicitação, os conversores / validadores necessários, as propriedades de bean gerenciado vinculado e métodos de ação.
Até que ponto no tempo o JSF salva o estado dos componentes da UI no lado do servidor e quando exatamente as informações de estado do componente da UI são removidas da memória do servidor?
Essas duas perguntas parecem resumir-se na mesma. De qualquer forma, isso é específico da implementação e também depende se o estado é salvo no servidor ou cliente. Uma implementação um pouco decente o removerá quando ele tiver expirado ou quando a fila estiver cheia. Mojarra, por exemplo, tem um limite padrão de 15 visualizações lógicas quando o salvamento de estado é definido como sessão. Isso é configurável com o seguinte parâmetro de contexto em web.xml
:
<context-param>
<param-name>com.sun.faces.numberOfLogicalViews</param-name>
<param-value>15</param-value>
</context-param>
Consulte também Mojarra FAQ para outros parâmetros específicos de Mojarra e esta resposta relacionada com.sun.faces.numberOfViewsInSession vs com.sun.faces.numberOfLogicalViews
Conforme um usuário logado no aplicativo navega pelas páginas, o estado dos componentes continuará se acumulando no servidor?
Tecnicamente, isso depende da implementação. Se você está falando sobre navegação página a página (apenas solicitações GET), o Mojarra não salvará nada na sessão. No entanto, se forem solicitações POST (formulários com links de comando / botões), o Mojarra salvará o estado de cada formulário na sessão até o limite máximo. Isso permite que o usuário final abra vários formulários em diferentes guias do navegador na mesma sessão.
Ou, quando o salvamento de estado é definido como cliente, o JSF não armazenará nada na sessão. Você pode fazer isso através do seguinte parâmetro de contexto em web.xml
:
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
Em seguida, ele será serializado em uma string criptografada em um campo de entrada oculto com o nome javax.faces.ViewState
do formulário.
Eu não entendo qual é a vantagem de manter o estado do componente de interface do usuário no lado do servidor. Não é suficiente passar diretamente os dados validados / convertidos para beans gerenciados? Posso / devo tentar evitá-lo?
Isso não é suficiente para garantir a integridade e robustez do JSF. JSF é uma estrutura dinâmica com um único ponto de controle de entrada. Sem um gerenciamento de estado, seria possível falsificar / hackear solicitações HTTP de uma determinada maneira (por exemplo disabled
, manipulação readonly
e rendered
atributos), para permitir que o JSF fizesse coisas diferentes - e potencialmente perigosas. Estaria até sujeito a ataques CSRF e phishing.
E isso não vai consumir muita memória no lado do servidor, se houver milhares de sessões de usuário simultâneas? Eu tenho um aplicativo onde os usuários podem postar blogs sobre determinados tópicos. Esses blogs são muito grandes. Quando houver postagem de volta ou solicitação de visualização dos blogs, os grandes blogs serão salvos como parte do estado dos componentes. Isso consumiria muita memória. Isso não é uma preocupação?
A memória é particularmente barata. Basta dar ao appserver memória suficiente. Ou se a largura de banda da rede for mais barata para você, basta alternar a economia de estado para o cliente. Para encontrar a melhor correspondência, apenas teste e crie o perfil de seu webapp com a quantidade máxima esperada de usuários simultâneos e, em seguida, dê ao appserver 125% ~ 150% da memória máxima medida.
Observe que o JSF 2.0 melhorou muito no gerenciamento de estado. É possível salvar o estado parcial (por exemplo, apenas o <h:form>
será salvo em vez de todo o material de <html>
todo o caminho até o fim). Mojarra, por exemplo, faz isso. Um formulário médio com 10 campos de entrada (cada um com um rótulo e uma mensagem) e 2 botões não ocuparia mais do que 1 KB. Com 15 visualizações na sessão, isso não deve ser superior a 15 KB por sessão. Com aproximadamente 1000 sessões de usuário simultâneas, isso não deve ser superior a 15 MB.
Sua preocupação deve estar mais focada nos objetos reais (beans gerenciados e / ou mesmo entidades de banco de dados) no escopo da sessão ou do aplicativo. Já vi muitos códigos e projetos que duplicam desnecessariamente toda a tabela do banco de dados na memória do Java, como um bean com escopo de sessão em que o Java é usado em vez de SQL para filtrar / agrupar / organizar os registros. Com ~ 1000 registros, isso ultrapassaria facilmente 10 MB por sessão de usuário .