web-dev-qa-db-fra.com

Quelle est la différence entre redirection et navigation / transfert et quand utiliser quoi?

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.

32
ad-inf

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:

  • Le client envoie une demande HTTP à somepage.xhtml.
  • Le serveur renvoie une réponse HTTP avec l'en-tête Location: newpage.xhtml
  • Le client envoie une demande HTTP à newpage.xhtml (Cela se reflète dans la barre d'adresse du navigateur!)
  • Le serveur renvoie une réponse HTTP avec un contenu de 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.

  • Le client envoie une demande HTTP à somepage.xhtml.
  • Le serveur renvoie une réponse HTTP avec un contenu de 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 IllegalStateExceptions 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().

Voir également:

79
BalusC