Quelle est la différence entre redirect et navigation/forward et quand utiliser quoi?
Quelle est la différence entre une navigation dans 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 à moins que faces-redirect=true
soit ajouté à la chaîne de requête de l'URL de navigation. Cependant, dans mon cas, ajouter faces-redirect=true
déclenche une erreur si je veux rediriger vers une page non-JSF comme une page HTML ordinaire.
et une autre option est comme BalusC suggéré à JSF 2.0 erreur de redirection
1 réponses
tout d'abord, le terme "redirect" 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 là la nouvelle URL sur laquelle le client doit envoyer une nouvelle demande GET. Donc en gros:
- le Client envoie une requête HTTP à
somepage.xhtml
.
Le serveur - renvoie une réponse HTTP avec
Location: newpage.xhtml
en-tête
Le Client - envoie une requête HTTP à
newpage.xhtml
(cela se reflète dans la barre d'adresse du navigateur!)
Le serveur - renvoie une réponse HTTP avec le contenu de
newpage.xhtml
.
vous pouvez le suivre avec l'ensemble d'outils de développement builtin/addon du webbrowser. Appuyez sur F12 dans Chrome/IE9 / Firebug et vérifiez la section "Réseau" pour le voir.
le gestionnaire de navigation JSF n'envoie pas de redirection. Il utilise plutôt le contenu de la page cible comme réponse HTTP.
- le Client envoie une requête HTTP à
somepage.xhtml
.
Le serveur - renvoie une réponse HTTP avec le contenu de
newpage.xhtml
.
cependant comme la requête HTTP originale était somepage.xhtml
, L'URL dans la barre d'adresse du navigateur reste inchangée. Si vous êtes familier avec l'API servlet de base , alors 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()
sur elle est l'usage approprié; non, ce n'est pas l'usage approprié. Vos journaux de serveur seront encombrés de IllegalStateException
parce que de cette façon vous ne dites pas à JSF que vous avez déjà pris le contrôle de la gestion de la réponse et donc JSF ne devrait pas faire son travail de gestion de la réponse par défaut. Vous devriez en fait exécuter FacesContext#responseComplete()
par la suite.
aussi, chaque fois que vous avez besoin d'importer quelque chose du paquet javax.servlet.*
dans un artefact JSF comme un haricot géré, vous devriez absolument arrêter d'écrire du code et réfléchir à deux fois si vous faites vraiment les choses de la bonne façon et vous demander s'il n'y a pas déjà une "manière JSF standard" pour ce que vous essayez d'atteindre et/ou si la tâche appartient vraiment dans un haricot géré JSF (il y a à savoir certains cas où un simple servlet filtre aurait été un meilleur endroit).
la bonne façon d'effectuer une redirection dans JSF est d'utiliser faces-redirect=true
chaîne de requête dans le résultat de l'action:
public String submit() {
// ...
return "/newpage.xhtml?faces-redirect=true";
}
Ou à l'aide de ExternalContext#redirect()
lorsque vous n'êtes pas à l'intérieur d'une méthode d'action comme une requête ajax ou pré-rendu méthode d'écouteur:
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
, il suffit que l'exception passe par throws
, le servletcontainer s'en chargera)
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 à la raison pour laquelle le gestionnaire de navigation échoue pour les fichiers "HTML simples", c'est simplement parce que le gestionnaire de navigation ne peut traiter que les vues JSF, pas d'autres fichiers. Vous devriez utiliser ExternalContext#redirect()
alors.