39 votes

Y a-t-il des moyens astucieux de gérer le contexte dans une application Web ?

En Java, les applications Web sont regroupées dans des WAR. Par défaut, de nombreux conteneurs de servlets utilisent le nom du WAR comme nom de contexte pour l'application.

Ainsi, myapp.war est déployé dans http://example.com/myapp .

Le problème est que la webapp considère que sa "Racine" est, eh bien, "Racine", ou simplement "/", alors que HTML considérerait que la Racine de votre application est "/myapp".

L'API Servlet et JSP disposent de fonctions permettant de gérer cette situation. Par exemple, si, dans une servlet, vous faites : response.sendRedirect("/mypage.jsp"), le conteneur ajoutera le contexte et créera l'url : http://example.com/myapp/mypage.jsp ".

Cependant, vous ne pouvez pas le faire avec, par exemple, la balise IMG en HTML. Si vous faites <img src="/myimage.gif"/>, vous obtiendrez probablement un message 404, car ce que vous vouliez vraiment était "/myapp/myimage.gif".

De nombreux frameworks ont des balises JSP qui sont également sensibles au contexte, et il existe différentes manières de créer des URL correctes dans JSP (aucune n'est particulièrement élégante).

C'est un problème délicat pour les codeurs que de savoir quand utiliser une url "App Relative" ou une url absolue.

Enfin, il y a la question du code Javascript qui doit créer des URL à la volée, et des URL intégrées dans les CSS (pour les images d'arrière-plan et autres).

Je suis curieux de savoir quelles techniques les autres utilisent pour atténuer et contourner ce problème. Beaucoup se contentent de le coder en dur, soit pour le serveur Root, soit pour le contexte qu'ils utilisent. Je connais déjà la réponse, ce n'est pas ce que je recherche.

Que faites-vous ?

24voto

Phill Sacre Points 16238

Vous pouvez utiliser JSTL pour créer des urls.

Par exemple, <c:url value="/images/header.jpg" /> préfixera le contexte Root.

Avec les CSS, ce n'est généralement pas un problème pour moi.

J'ai une structure web Root comme ceci :

/css
/images

Dans le fichier CSS, il suffit alors d'utiliser des URL relatives (../images/header.jpg) et il n'est pas nécessaire de tenir compte du contexte Root.

En ce qui concerne le JavaScript, ce qui fonctionne pour moi, c'est d'inclure un JavaScript courant dans l'en-tête de la page, comme ceci :

<script type="text/javascript">
var CONTEXT_ROOT = '<%= request.getContextPath() %>';
</script>

Ensuite, vous pouvez utiliser le contexte Root dans tous vos scripts (ou, vous pouvez définir une fonction pour construire les chemins - ce qui peut être un peu plus flexible).

Évidemment, tout cela dépend de l'utilisation que vous faites des JSP et de JSTL, mais j'utilise JSF avec des Facelets et les techniques impliquées sont similaires - la seule vraie différence est d'obtenir le contexte Root d'une manière différente.

1 votes

Connaissez-vous un moyen de le faire si vous n'utilisez pas JSP ? Ce serait bien de pouvoir définir le nom de l'application dans le fichier pom.xml ou similaire.

8voto

BalusC Points 498232

Pour les pages HTML, j'ai simplement défini le paramètre HTML <base> étiquette. Chaque lien relatif (c'est-à-dire ne commençant pas par scheme ou / ) deviendra relatif à celui-ci. Il n'y a pas de manière propre de le saisir immédiatement par HttpServletRequest Nous avons donc besoin d'une petite aide de JSTL ici.

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<c:set var="req" value="${pageContext.request}" />
<c:set var="url">${req.requestURL}</c:set>
<c:set var="uri">${req.requestURI}</c:set>

<!DOCTYPE html>
<html lang="en">
  <head>
    <base href="${fn:substring(url, 0, fn:length(url) - fn:length(uri))}${req.contextPath}/" />
    <link rel="stylesheet" href="css/default.css">
    <script src="js/default.js"></script>
  </head>
  <body>
    <img src="img/logo.png" />
    <a href="other.jsp">link</a>
  </body>
</html>

Cela comporte toutefois une mise en garde : les ancrages (les #identifier URL) deviendront également relatifs au chemin de base. Si vous avez l'un d'entre eux, vous souhaitez qu'il devienne relatif à l'URL de la demande (URI) à la place. Donc, changez comme suit

<a href="#identifier">jump</a>

à

<a href="${uri}#identifier">jump</a>

En JS, vous pouvez simplement accéder au <base> du DOM lorsque vous souhaitez convertir une URL relative en URL absolue.

var base = document.getElementsByTagName("base")[0].href;

Ou si vous faites du jQuery

var base = $("base").attr("href");

En CSS, les URL des images sont relatives à l'URL de la feuille de style elle-même. Donc, il suffit de déposer les images dans un dossier relatif à la feuille de style elle-même. Par exemple

/css/style.css
/css/images/foo.png

et les référencer comme suit

background-image: url('images/foo.png');

Si vous préférez déposer les images dans un dossier au même niveau que le dossier CSS.

/css/style.css
/images/foo.png

puis utiliser ../ pour aller dans le dossier parent commun

background-image: url('../images/foo.png');

Voir aussi :

4voto

Demwis Points 1670

Je suis d'accord avec tardif . J'ai prêté mon attention aux filtres aussi et j'ai trouvé la solution face au projet. UrlRewriteFilter . La configuration simple est la suivante :

<rule>
    <from>^.+/resources/(.*)$</from>
    <to>/resources/$1</to>
</rule>

permet de transférer toutes les demandes pour */resources path vers /resources pass (y compris le préfixe du chemin du contexte). Ainsi, je peux simplement mettre toutes mes images et CSS dossiers sous ressources et continuer à utiliser des URL relatives dans mes styles pour les images d'arrière-plan et autres cas.

3voto

tardate Points 6809

L'API Servlet et JSP disposent pour aider à gérer cela. Par exemple, Par exemple, si, dans une servlet, vous faites : response.sendRedirect("/mypage.jsp"), le conteneur va ajouter le contexte et créera l'url : http://example.com/myapp/mypage.jsp ".

Ah, peut-être, peut-être pas - cela dépend de votre conteneur et de la spécification de la servlet !

De Servlet 2.3 : Nouvelles fonctionnalités exposées :

Et enfin, après un long débat par un groupe d'experts, l'API Servlet 2.3 a clarifié une fois pour toutes ce qui se passe lors d'un res.sendRedirect("/index.html") pour une servlet s'exécutant dans un contexte non-Root. Le problème est le suivant Servlet API 2.2 exige un chemin incomplet comme "/index.html". incomplet comme "/index.html" soit traduit par le traduit par le conteneur de servlets en un chemin complet, mais ne précise pas comment les chemins contextuels sont traités. Si la servlet effectuant l'appel est dans un contexte au niveau du chemin "/contextpath". l'URI de redirection doit-il traduire par rapport au conteneur Root ( http://server:port/index.html ) ou le racine du contexte ( http://server:port/contextpath/index.html ) ? Pour une portabilité maximale, il est impératif de définir le comportement ; Après un long débat, les experts ont ont choisi de traduire par rapport au racine du conteneur. Pour ceux qui veulent relative au contexte, vous pouvez ajouter la de la fonction getContextPath() à votre fichier URI.

Donc non, avec la 2.3 vos chemins sont pas automatiquement traduit pour inclure le chemin d'accès au contexte.

1voto

kosoant Points 5333

J'ai utilisé classes d'aide pour générer des balises img, etc. Cette classe d'aide s'occupe de préfixation des chemins avec le contextPath de l'application. (Cela fonctionne, mais je ne l'aime pas vraiment. Si quelqu'un a de meilleures alternatives, merci de le dire).

Pour les chemins dans les fichiers css, etc. J'utilise un Ant build script qui utilise un site.production.css pour le site.css dans l'environnement de production et un site.development.css dans l'environnement de développement.

Alternativement, j'utilise parfois un script Ant qui remplace @token@ des jetons avec des données appropriées pour différents environnements. Dans ce cas, le jeton @contextPAth@ sera remplacé par le chemin d'accès au contexte correct.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X