web-dev-qa-db-fra.com

Ajout de ressources externes (CSS / JavaScript / images, etc.) dans JSP

J'ai ajouté une feuille de style CSS externe à mon projet et placée dans le dossier WEB-CONTENTS de mon projet dans Eclipse. Lorsque je l'ai déployé sur le Tomcat, la feuille de style n'a pas été appliquée. Lorsque je l'ai débogué dans Chrome et que je l'ai ouvert, il m'a donné 404 file not found Erreur. Pourquoi est-ce et comment y remédier?

Voici le code:

<%@ page language="Java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@taglib prefix="c" uri="http://Java.Sun.com/jsp/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>joined now </title>

<link href="globalCSS.css" rel="stylesheet" type="text/css"/>

</head>
<body>
<div>this is at the top</div>
<c:import url="header.jsp" />
<c:import url="navigationBar.jsp" />  
<c:import url="leftpane.jsp" /> 
<c:import url="mainContent.jsp" /> 
<c:import url="rightpane.jsp" />
<c:import url="footer.jsp" />  
</body>
</html>
22
Vishal Anand

La raison pour laquelle vous obtenez le 404 File Not Found erreur, c'est que votre chemin vers CSS donné comme valeur à l'attribut href est manquant chemin de contexte .

Une URL de demande HTTP contient les parties suivantes:

http://[Host]:[port][request-path]?[query-string]

Le chemin de demande est en outre composé des éléments suivants:

  • Chemin de contexte: Une concaténation d'une barre oblique (/) avec la racine de contexte de l'application Web du servlet. Exemple: http://Host[:port]/context-root[/url-pattern]

  • Chemin du servlet: La section du chemin qui correspond à l'alias de composant qui a activé cette demande. Ce chemin commence par une barre oblique (/).

  • Info chemin: La partie du chemin de requête qui ne fait pas partie du chemin de contexte ou du chemin de servlet.

En savoir plus ici .


Solutions

Il existe plusieurs solutions à votre problème, en voici quelques-unes:

1) Utilisation de <c:url> tag de JSTL

Dans mes Java applications Web que j'utilisais habituellement <c:url> tag de JSTL lors de la définition du chemin vers CSS/JavaScript/image et d'autres ressources statiques. Ce faisant, vous pouvez être sûr que ces ressources sont référencées toujours par rapport au contexte de l'application (chemin du contexte).

Si vous dites que votre CSS se trouve dans le dossier WebContent, alors cela devrait fonctionner:

<link type="text/css" rel="stylesheet" href="<c:url value="/globalCSS.css" />" />

La raison pour laquelle cela fonctionne est expliquée dans la " Bibliothèque de balises standard JavaServer Pages ™" version 1.2 spécification chapitre 7.5 (accentuation du mien):

7,5 <c: url>
Construit une URL avec les règles de réécriture appropriées appliquées.
...
L'URL doit être soit une URL absolue commençant par un schéma (par exemple "http: // server/context/page.jsp"), soit une URL relative telle que définie par JSP 1.2 dans JSP.2.2.1 "Relative Spécification d'URL ". Par conséquent, une implémentation doit ajouter le chemin de contexte à une URL qui commence par une barre oblique (par exemple "/page2.jsp") pour que ces URL peut être correctement interprété par un navigateur client.

[~ # ~] note [~ # ~]
N'oubliez pas d'utiliser directive Taglib dans votre JSP pour pouvoir référencer balises JSTL . Voir également un exemple de page JSP ici .


2) Utilisation du langage d'expression JSP et des objets implicites

Une solution alternative utilise Expression Language (EL) pour ajouter le contexte d'application:

<link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath}/globalCSS.css" />

Ici, nous avons récupéré le chemin de contexte de l'objet request. Et pour accéder à l'objet de requête, nous avons utilisé le pageContext objet implicite .


3) Utilisation de <c:set> tag de JSTL

[~ # ~] clause de non-responsabilité [~ # ~]
L'idée de cette solution est tirée de ici .

Pour rendre l'accès au chemin de contexte plus compact que dans la solution №2, vous pouvez d'abord utiliser le JSTL <c:set> balise, définit la valeur d'une variable EL ou la propriété d'une variable EL dans l'une des étendues JSP (page, demande, session ou application) pour un accès ultérieur.

<c:set var="root" value="${pageContext.request.contextPath}"/>
...
<link type="text/css" rel="stylesheet" href="${root}/globalCSS.css" />

NOTE IMPORTANTE
Par défaut, pour définir la variable de cette manière, la balise JSP qui contient cette balise set doit être consultée au moins une fois (y compris en cas de définition de la valeur dans l'attribut application à l'aide de l'attribut scope, comme <c:set var="foo" value="bar" scope="application" />), avant d'utiliser cette nouvelle variable. Par exemple, vous pouvez avoir plusieurs fichiers JSP où vous avez besoin de cette variable. Vous devez donc éther a) les deux définissez le nouveau chemin de contexte de maintien de variable dans la portée ET accédez d'abord à ce JSP , avant d'utiliser cette variable dans d'autres fichiers JSP, ou b) définissez ce chemin de contexte contenant la variable dans CHAQUE fichier JSP, où vous devez y accéder.


4) Utilisation de ServletContextListener

Le moyen le plus efficace de rendre l'accès au chemin de contexte plus compact est de définir une variable qui contiendra le chemin de contexte et de le stocker dans application scope en utilisant un - Auditeur . Cette solution est similaire à la solution №3, mais l'avantage est que maintenant le chemin du contexte de maintien variable est défini juste au début de l'application Web et est disponible dans toute l'application, pas besoin d'étapes supplémentaires.

Nous avons besoin d'une classe qui implémente ServletContextListener interface. Voici un exemple d'une telle classe:

package com.example.listener;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class AppContextListener implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent event) {
        ServletContext sc = event.getServletContext();
        sc.setAttribute("ctx", sc.getContextPath());
    }

    @Override
    public void contextDestroyed(ServletContextEvent event) {}

}

Maintenant, dans un JSP, nous pouvons accéder à cette variable globale en utilisant EL:

<link type="text/css" rel="stylesheet" href="${ctx}/globalCSS.css" />

[~ # ~] note [~ # ~]
@ WebListener l'annotation est disponible depuis la version 3.0 du servlet. Si vous utilisez un conteneur de servlet ou un serveur d'applications qui prend en charge les anciennes spécifications de servlet, supprimez l'annotation @ WebServlet et configurez plutôt l'écouteur dans le descripteur de déploiement (Web. xml). Voici un exemple de fichier web.xml pour le conteneur qui prend en charge la version 2.5 maximale de Servlet (d'autres configurations sont omises par souci de concision):

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://Java.Sun.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://Java.Sun.com/xml/ns/javaee
                        http://Java.Sun.com/xml/ns/javaee/web-app_2_5.xsd"
    version="2.5">
    ...  
    <listener>
        <listener-class>com.example.listener.AppContextListener</listener-class>
    </listener>
    ...
</webapp>


5) Utilisation de scriptlets

Comme suggéré par l'utilisateur @ gavenkoa vous pouvez également utiliser scriptlets comme ceci:

<%= request.getContextPath() %>

Pour une si petite chose, c'est probablement OK, notez juste que généralement l'utilisation de scriptlets dans JSP est déconseillée .


Conclusion

Personnellement, je préfère soit la première solution (utilisée dans mes projets précédents la plupart du temps) soit la seconde, car elles sont les plus claires, intuitives et sans ambiguïté (IMHO). Mais vous choisissez ce qui vous convient le mieux.


D'autres pensées

Vous pouvez déployer votre application web en tant que application par défaut (c'est-à-dire dans le contexte racine par défaut ), de sorte qu'elle peut être accédé sans spécifier de chemin de contexte . Pour plus d'informations, lisez la section "Mise à jour" ici .

37
informatik01

En utilisant le code suivant, vous résolvez cette question .... Si vous exécutez un fichier à l'aide d'un serveur localhost, ce problème est résolu en suivant le code de page Jsp. Ce code met la balise Head Head dans le fichier jsp

<style type="text/css">
    <%@include file="css/style.css" %>
</style>
<script type="text/javascript">
    <%@include file="js/script.js" %>
</script>
2
Parth Patel