web-dev-qa-db-fra.com

Comment obtenir l'URL de base?

J'ai cette structure:

WebContent
    resources
        components
            top.xhtml

    company
        about_us.xhtml

    index.xhtml

top.xhtml est un composant utilisé dans index.xthml et about_us.xhtml aussi.

top.xhtml

<ul>
    <li><a href="index.xhtml">Home</a></li>
    <li><a href="company/about_us.xhtml">About us</a></li>
    ...
</ul>

Mon problème est donc, quand la page en cours est index.xhtml le composant génère correctement les URL, mais lorsque la page en cours est about_us.xhtml, il génère des URL incorrectes. Je ne peux pas utiliser de chemin relatif car il va générer une mauvaise URL aussi. Je pense que c'est parce que le composant est basé sur le chemin actuel du *.xhtml page.

La seule solution que j'ai pu trouver est la suivante:

<ul>
    <li><a href="${pageContext.request.contextPath}/webname/index.xhtml">Home</a></li>
    <li><a href="${pageContext.request.contextPath}/webname/about_us.xhtml">About us</a></li>
    ...
</ul>

Mais je pense que ce n'est pas "élégant" du tout. Des idées?

66
Valter Silva

Les URL ne sont pas résolues en fonction de la structure de fichier côté serveur. Les URL sont résolues en fonction des adresses Web publiques réelles des ressources en question. C'est le navigateur Web qui doit les invoquer, pas le serveur Web.

Il y a plusieurs façons d'atténuer la douleur:

JSF EL propose un raccourci pour ${pageContext.request} Avec une saveur de #{request}:

<li><a href="#{request.contextPath}/index.xhtml">Home</a></li>
<li><a href="#{request.contextPath}/about_us.xhtml">About us</a></li>

Vous pouvez éventuellement utiliser <c:set> balise pour la rendre encore plus courte. Mettez-le quelque part dans le modèle principal, il sera disponible pour toutes les pages:

<c:set var="root" value="#{request.contextPath}/" />
...
<li><a href="#{root}index.xhtml">Home</a></li>
<li><a href="#{root}about_us.xhtml">About us</a></li>

JSF 2.x offre le <h:link> Qui peut prendre un ID de vue relatif à la racine de contexte dans outcome et ajoute le chemin de contexte et le mappage FacesServlet automatiquement:

<li><h:link value="Home" outcome="index" /></li>
<li><h:link value="About us" outcome="about_us" /></li>

HTML propose la balise <base> qui rend toutes les URL relatives du document relatives à cette base. Vous pourriez vous en servir. Mettez-le dans le <h:head>.

<base href="#{request.requestURL.substring(0, request.requestURL.length() - request.requestURI.length())}#{request.contextPath}/" />
...
<li><a href="index.xhtml">Home</a></li>
<li><a href="about_us.xhtml">About us</a></li>

(note: cela nécessite EL 2.2, sinon vous feriez mieux d'utiliser JSTL fn:substring(), voir aussi cette réponse )

Cela devrait aboutir dans le HTML généré quelque chose comme

<base href="http://example.com/webname/" />

Notez que la balise <base> A une mise en garde: elle crée également des ancres de saut de la page telles que <a href="#top">! Voir aussi Est-il recommandé d'utiliser la balise <base> html? Dans JSF, vous pouvez le résoudre comme <a href="#{request.requestURI}#top">top</a> Ou <h:link value="top" fragment="top" />.

140
BalusC

Variation JSTL 1.2 tirée de la réponse BalusC

<c:set var="baseURL" value="${pageContext.request.requestURL.substring(0, pageContext.request.requestURL.length() - pageContext.request.requestURI.length())}${pageContext.request.contextPath}/" />

<head>
  <base href="${baseURL}" />
1
JET