Qual é a diferença entre redirecionamento e navegação / encaminhamento e quando usar o que?

Qual é a diferença entre uma navegação no JSF

FacesContext context = FacesContext.getCurrentInstance(); context.getApplication().getNavigationHandler().handleNavigation(context, null, url); 

e um redirecionamento

 HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse(); response.sendRedirect(url); 

e como decidir quando usar o que?

O problema com a navegação é que o URL da página não é alterado, a menos que faces-redirect=true seja adicionado à string de consulta do URL de navegação. No entanto, no meu caso, adicionar faces-redirect=true lançará um erro se eu quiser redirect para uma página não-JSF como uma página HTML simples.

E outra opção é como BalusC sugerido no erro de redirecionamento JSF 2.0

Primeiro de tudo, o termo “redirecionamento” está no mundo de desenvolvimento web a ação de enviar ao cliente uma resposta HTTP vazia com apenas um header de Location com o novo URL em que o cliente tem que enviar uma nova solicitação GET. Então, basicamente:

  • Cliente envia uma solicitação HTTP para somepage.xhtml .
  • O servidor envia uma resposta HTTP de volta com o Location: newpage.xhtml header
  • O cliente envia uma solicitação HTTP para newpage.xhtml (isso se reflete na barra de endereço do navegador!)
  • O servidor envia uma resposta HTTP de volta com o conteúdo de newpage.xhtml .

Você pode rastreá-lo com o conjunto de ferramentas de desenvolvedor embutido / addon do webbrowser. Pressione F12 no Chrome / IE9 / Firebug e verifique a seção “Rede” para vê-lo.

O manipulador de navegação do JSF não envia um redirecionamento. Em vez disso, ele usa o conteúdo da página de destino como resposta HTTP.

  • Cliente envia uma solicitação HTTP para somepage.xhtml .
  • O servidor envia uma resposta HTTP de volta com o conteúdo de newpage.xhtml .

No entanto, como a solicitação HTTP original foi para somepage.xhtml , a URL na barra de endereços do navegador permanece inalterada. Se você estiver familiarizado com a API de Servlet básica , deve entender que isso tem o mesmo efeito que RequestDispatcher#forward() .


Quanto a saber se puxar o HttpServletResponse sob os capuzes do JSF e chamar sendRedirect() nele é o uso correto; não, esse não é o uso correto. Os logs do seu servidor ficarão cheios de IllegalStateException porque, dessa maneira, você não está dizendo ao JSF que você já assumiu o controle da manipulação de respostas e, portanto, o JSF não deve executar o trabalho de manipulação de resposta padrão. Você deve, de fato, estar executando FacesContext#responseComplete() depois.

Além disso, toda vez que precisar importar algo do pacote javax.servlet.* Em um artefato JSF como um bean gerenciado, você deve parar de escrever código e pensar duas vezes se realmente estiver fazendo as coisas da maneira certa e se perguntar se não há já é um “modo JSF padrão” para o que você está tentando alcançar e / ou se a tarefa realmente pertence a um bean gerenciado JSF (existem alguns casos em que um filtro de servlet simples teria sido um lugar melhor).

A maneira correta de executar um redirecionamento no JSF está usando faces-redirect=true query string no resultado da ação:

 public String submit() { // ... return "/newpage.xhtml?faces-redirect=true"; } 

Ou usando ExternalContext#redirect() quando você não está dentro de um método de ação, como um método ajax ou listener prerender:

 public void listener() throws IOException { // ... ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext(); ec.redirect(ec.getRequestContextPath() + "/newpage.xhtml"); } 

(sim, você não precisa colocar um try-catch torno dele em IOException , apenas deixe a exceção passar por throws , o servletcontainer irá lidar com isso)

Ou usando o NavigationHandler#handleNavigation() em casos específicos, se você estiver usando casos de navegação XML e / ou um manipulador de navegação personalizado com algum ouvinte incorporado:

 public void listener() { // ... FacesContext fc = FacesContext.getCurrentInstance(); NavigationHandler nh = fc.getApplication().getNavigationHandler(); nh.handleNavigation(fc, null, "/newpage.xhtml?faces-redirect=true"); } 

Quanto ao motivo pelo qual o manipulador de navegação falha para arquivos “HTML simples”, isso ocorre simplesmente porque o manipulador de navegação só pode processar visualizações JSF, e não outros arquivos. Você deve estar usando ExternalContext#redirect() então.

Veja também:

  • Como navegar no JSF? Como fazer o URL refletir a página atual (e não a anterior)
  • Quando devo usar h: outputLink em vez de h: commandLink?