Como navegar no JSF? Como fazer o URL refletir a página atual (e não a anterior)

Atualmente estou aprendendo JSF e fiquei bastante surpreso e perplexo quando percebi que sempre que usamos , o comportamento padrão do JSF é sempre mostrar a URL da página anterior no navegador, em oposição à URL do a página atual .

Eu entendo que isso tem a ver com a forma como o JSF sempre envia um formulário para a mesma página e depois apenas renderiza qualquer página que o controller devolve ao navegador, que não sabe que o local da página foi alterado.

Parece que o JSF existe há tempo suficiente para que haja uma maneira limpa e sólida de lidar com isso. Em caso afirmativo, você se importaria de compartilhar?

Eu encontrei várias soluções alternativas, mas infelizmente nada que parece ser uma solução sólida real.

  • Basta aceitar que o URL é enganoso.
  • Anexar "?faces-redirect=true" ao valor de retorno da ação de cada bean e, em seguida,
    • descobrir como replace @RequestScoped com outra coisa (Flash Scopes, conversação CDI, @SessionScoped, …).
    • aceite ter duas viagens de ida e volta HTTP para cada ação do usuário.
  • Use algum método (por exemplo, biblioteca de terceiros ou código personalizado) para ocultar o nome da página no URL, sempre usando o mesmo URL genérico para cada página.

Se "?faces-redirect=true" é tão bom quanto possível, existe uma maneira de configurar um aplicativo inteiro para tratar todos os pedidos dessa maneira?

De fato, o JSF como sendo uma estrutura MVC direcionada a um aplicativo baseado em formulário envia o formulário POST para o mesmo URL de onde a página com o foi solicitada. Você pode confirmar isso observando a URL

da saída HTML gerada. Isso está em termos de desenvolvimento da Web caracterizados como postagem . Por padrão, uma navegação em um postback não causa uma nova solicitação para o novo URL, mas carrega a página de destino como conteúdo da resposta. Isso é realmente confuso quando você simplesmente quer navegação de página para página.

Geralmente, a abordagem correta de navegação / redirecionamento depende dos requisitos de negócios e da idempotência (leia-se: “bookmarkability”) da solicitação.

  • Se o pedido é idempotente, basta usar um formulário GET / link em vez do formulário POST (ou seja, usar

    , ou vez de e ).
    Por exemplo, navegação de página para página, formulário de pesquisa semelhante ao Google, etc.

  • Se a requisição não for idempotente, apenas mostre os resultados condicionalmente na mesma view (isto é, retorne null ou void e faça uso de, por exemplo, e / ou rendered ).
    Por exemplo, input / edição de dados, assistente de várias etapas, modal dialog, formulário de confirmação, etc.

  • Se a solicitação não for idempotente, mas a página de destino for idempotente, basta enviar um redirecionamento após o POST (ou seja, retornar o resultado com ?faces-redirect=true ou ).
    Por exemplo, mostrando a lista de todos os dados após a edição bem-sucedida, redirect após o login, etc.

Observe que a navegação de página para página é geralmente idempotente e é nesse ponto que muitos iniciadores do JSF falham ao abusar de links / botões de comando para isso e depois reclamam que as URLs não mudam. Observe também que os casos de navegação são muito raramente usados ​​em aplicações do mundo real que são desenvolvidas com relação a SEO / UX e é aí que muitos tutoriais JSF falham, permitindo que os leitores acreditem o contrário.

Observe também que o uso do POST não é absolutamente “mais seguro” do que o GET porque os parâmetros da solicitação não são imediatamente visíveis na URL. Eles ainda são visíveis no corpo da solicitação HTTP e ainda podem ser manipulados. Portanto, não há absolutamente nenhuma razão para preferir o POST a solicitações idempotentes por “segurança”. A segurança real está no uso de HTTPS em vez de HTTP e na verificação de methods de serviço de negócios se o usuário conectado no momento tiver permissão para consultar a entidade X, manipular a entidade X etc. Uma estrutura de segurança decente oferece annotations para isso.

Veja também:

  • Qual é a diferença entre redirecionamento e navegação / encaminhamento e quando usar o que?
  • JSF implícita vs. navegação explícita
  • Marcabilidade por meio do recurso View Parameters
  • O que pode ser usado para , e ?
  • Quando devo usar h: outputLink em vez de h: commandLink?
  • Criando páginas de detalhes mestre para entidades, como vinculá-las e qual escopo de bean escolher
  • Retendo parâmetros de string de consulta de solicitação GET no envio de formulário JSF
  • Passa um object entre os beans @ViewScoped sem usar os parâmetros GET