web-dev-qa-db-fra.com

Comment naviguer dans JSF? Comment faire en sorte que l'URL reflète la page actuelle (et non la précédente)

J'apprends actuellement JSF et j'ai été plutôt étonné et perplexe quand j'ai réalisé que chaque fois que nous utilisons <h:form>, le comportement standard de JSF est de toujours me montrer l'URL de la page précédente dans le navigateur, par opposition à l'URL de la page actuelle .

Je comprends que cela a à voir avec la façon dont JSF publie toujours un formulaire sur la même page, puis restitue la page que le contrôleur lui rend au navigateur qui ne sait pas que l'emplacement de la page a changé.

Il semble que JSF existe depuis assez longtemps pour qu'il y ait un moyen propre et solide de gérer cela. Si oui, cela vous dérangerait-il de partager?

J'ai trouvé diverses solutions de contournement, mais malheureusement rien qui semble être une vraie solution solide.

  • Acceptez simplement que l'URL est trompeuse.
  • Ajouter "?faces-redirect=true" à la valeur de retour de chaque action du bean puis
    • comprendre comment remplacer @RequestScoped avec autre chose (Flash Scopes, conversation CDI, @SessionScoped, ...).
    • acceptez d'avoir deux allers-retours HTTP pour chaque action de l'utilisateur.
  • Utilisez une méthode (par exemple, une bibliothèque tierce ou un code personnalisé) pour masquer le nom de la page dans l'URL, en utilisant toujours la même URL générique pour chaque page.

Si "?faces-redirect=true" est aussi bon que possible, existe-t-il un moyen de configurer une application entière pour traiter toutes les demandes de cette façon?

48
Student

En effet, JSF comme étant un framework MVC ciblé par application basée sur un formulaire soumet le formulaire POST à la même URL que celle où la page avec le <h:form> Est demandée. Vous pouvez confirmer en regardant l'URL <form action> de la sortie HTML générée. Ceci est en termes de développement web caractérisé comme postback . Une navigation sur un postback ne provoque pas par défaut une nouvelle requête vers la nouvelle URL, mais charge la page cible en tant que contenu de la réponse. Cela est en effet déroutant lorsque vous souhaitez simplement une navigation de page en page.

En règle générale, la bonne approche en matière de navigation/redirection dépend des besoins de l'entreprise et de la idempotence (lire: "bookmarkability") de la demande (note: pour des exemples de code concrets, voir les liens "Voir aussi" au dessous de).

  • Si la demande est idempotente, utilisez simplement un formulaire/lien GET au lieu de POST form (c'est-à-dire utilisez <a>, <form>, <h:link> Ou <h:button> Au lieu de <h:form> Et <h:commandXxx>).
    Par exemple, navigation de page en page, formulaire de recherche de type Google, etc.

  • Si la requête n'est pas idempotente, affichez simplement les résultats de manière conditionnelle dans la même vue (c'est-à-dire renvoyez null ou void de la méthode d'action et utilisez par exemple <h:message(s)> et/ou rendered).
    Par exemple, saisie/modification de données sur la page, assistant en plusieurs étapes, boîte de dialogue modale, formulaire de confirmation, etc.

  • Si la demande n'est pas idempotente, mais que la page cible est idempotente, envoyez simplement une redirection après POST (c'est-à-dire renvoyez le résultat avec ?faces-redirect=true À partir de la méthode d'action, ou appelez manuellement ExternalContext#redirect(), ou mettez <redirect/> dans le cas de navigation XML hérité).
    Par exemple, afficher la liste de toutes les données après une édition réussie, rediriger après la connexion, etc.

Notez que la navigation de page à page pure est généralement idempotente et c'est là que de nombreux démarreurs JSF échouent en abusant des liens/boutons de commande pour cela et se plaignent ensuite que les URL ne changent pas. Notez également que les cas de navigation sont très rarement utilisés dans les applications du monde réel qui sont développées en ce qui concerne le SEO/UX et c'est là que de nombreux tutoriels JSF échouent en laissant les lecteurs croire le contraire.

Notez également que l'utilisation de POST n'est absolument pas "plus sécurisée" que GET car les paramètres de requête ne sont pas immédiatement visibles dans l'URL. Ils sont toujours visibles dans le corps de la requête HTTP et toujours manipulables. Il y a donc absolument aucune raison de préférer POST pour les demandes idempotentes pour des raisons de "sécurité". La vraie sécurité est d'utiliser HTTPS au lieu de HTTP et de vérifier les méthodes de service commercial si l'utilisateur actuellement connecté est autorisé à interroger l'entité X, ou manipuler l'entité X, etc. Un cadre de sécurité décent propose des annotations pour cela.

Voir également:

73
BalusC