Quelle est la différence entre une navigation en JSF
FacesContext context = FacesContext.getCurrentInstance();
context.getApplication().getNavigationHandler().handleNavigation(context, null, url);
et une redirection
HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
response.sendRedirect(url);
et comment décider quand utiliser quoi?
Le problème avec la navigation est que l'URL de la page ne change pas sauf si faces-redirect=true
est ajouté à la chaîne de requête de l'URL de navigation. Cependant, dans mon cas, en ajoutant faces-redirect=true
génère une erreur si je souhaite rediriger vers une page non JSF comme une page HTML standard.
Et une autre option est comme BalusC l'a suggéré à erreur de redirection JSF 2.
Tout d'abord, le terme "rediriger" est dans le monde du développement web l'action d'envoyer au client une réponse HTTP vide avec juste un en-tête Location
avec la nouvelle URL sur laquelle le client doit envoyer un tout nouveau GET demande. Donc en gros:
somepage.xhtml
.Location: newpage.xhtml
newpage.xhtml
(Cela se reflète dans la barre d'adresse du navigateur!)newpage.xhtml
.Vous pouvez le suivre avec le jeu d'outils de développement intégré/addon du navigateur Web. Appuyez sur F12 dans Chrome/IE9/Firebug et consultez la section "Réseau" pour le voir.
Le gestionnaire de navigation JSF n'envoie pas de redirection. Au lieu de cela, il utilise le contenu de la page cible comme réponse HTTP.
somepage.xhtml
.newpage.xhtml
.Cependant, comme la demande HTTP d'origine était de somepage.xhtml
, L'URL dans la barre d'adresse du navigateur reste inchangée. Si vous connaissez API Servlet de base , vous devez comprendre que cela a le même effet que RequestDispatcher#forward()
.
Quant à savoir si tirer le HttpServletResponse
sous les hottes JSF et appeler sendRedirect()
dessus est la bonne utilisation; non, ce n'est pas le bon usage. Vos journaux de serveur seront encombrés de IllegalStateException
s car de cette façon, vous ne dites pas à JSF que vous avez déjà pris le contrôle de la gestion des réponses et que JSF ne devrait donc pas faire son travail de gestion des réponses par défaut. Vous devriez en fait exécuter FacesContext#responseComplete()
par la suite.
De plus, chaque fois que vous devez importer quelque chose du package javax.servlet.*
Dans un artefact JSF comme un bean géré, vous devez absolument arrêter d'écrire du code et réfléchir à deux fois si vous faites vraiment les choses correctement et demandez-vous s'il y a n'est pas déjà un "moyen JSF standard" pour tout ce que vous essayez de réaliser et/ou si la tâche appartient vraiment à un bean géré JSF (il y a notamment des cas où un simple filtre de servlet serait ont été un meilleur endroit).
La bonne façon d'effectuer une redirection dans JSF utilise la chaîne de requête faces-redirect=true
Dans le résultat de l'action:
public String submit() {
// ...
return "/newpage.xhtml?faces-redirect=true";
}
Ou en utilisant ExternalContext#redirect()
lorsque vous n'êtes pas dans une méthode d'action telle qu'une méthode d'écoute ajax ou prerender:
public void listener() throws IOException {
// ...
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
ec.redirect(ec.getRequestContextPath() + "/newpage.xhtml");
}
(oui, vous n'avez pas besoin de mettre un try-catch
autour de lui sur IOException
, laissez simplement l'exception passer par throws
, le servletcontainer le gérera)
Ou en utilisant NavigationHandler#handleNavigation()
dans des cas spécifiques si vous utilisez des cas de navigation XML et/ou un gestionnaire de navigation personnalisé avec un écouteur intégré:
public void listener() {
// ...
FacesContext fc = FacesContext.getCurrentInstance();
NavigationHandler nh = fc.getApplication().getNavigationHandler();
nh.handleNavigation(fc, null, "/newpage.xhtml?faces-redirect=true");
}
Quant à savoir pourquoi le gestionnaire de navigation échoue pour les fichiers "HTML brut", c'est simplement parce que le gestionnaire de navigation peut traiter uniquement les vues JSF, pas les autres fichiers. Vous devriez alors utiliser ExternalContext#redirect()
.