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

31
demandé sur Community 2012-07-01 00:19:04

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.

voir aussi:

79
répondu BalusC 2017-05-23 12:02:16