Der Browser kann beim Aufrufen eines Servlets, das an eine JSP weiterleitet, nicht auf relative Ressourcen wie CSS, Bilder und Links zugreifen / diese finden

82

Ich habe Probleme beim Laden von CSS und Bildern und beim Erstellen von Links zu anderen Seiten, wenn ein Servlet an eine JSP weitergeleitet wird. Insbesondere wenn ich meine <welcome-file>auf setze , index.jspwird das CSS geladen und meine Bilder werden angezeigt. Allerdings, wenn ich mein Set <welcome-file>auf , HomeServletdie nach vorne zu steuern index.jsp, wird die CSS nicht angewandt wird und meine Bilder werden nicht angezeigt werden.

Meine CSS-Datei befindet sich in web/styles/default.css.
Meine Bilder sind in web/images/.

Ich verlinke wie folgt mit meinem CSS:

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

Ich zeige meine Bilder wie folgt an:

<img src="images/image1.png" alt="Image1" />

Wie wird dieses Problem verursacht und wie kann ich es lösen?


Update 1 : Ich habe die Struktur der Anwendung sowie einige andere Informationen hinzugefügt, die möglicherweise hilfreich sind.

Alt-Text

Die header.jspDatei ist die Datei, die das Link-Tag für das CSS enthält. Das HomeServletist wie mein welcome-filein gesetzt web.xml:

<welcome-file-list>
    <welcome-file>HomeServlet</welcome-file>
</welcome-file-list>

Das Servlet wird wie folgt deklariert und zugeordnet web.xml:

<servlet>
    <servlet-name>HomeServlet</servlet-name>
    <servlet-class>com.brianblog.frontend.HomeServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>HomeServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

Update 2 : Ich habe das Problem endlich gefunden - mein Servlet wurde falsch zugeordnet. Wenn Sie ein Servlet als Ihr Servlet festlegen <welcome-file>, kann es anscheinend kein URL-Muster haben /, was ich irgendwie komisch finde, denn würde das nicht für das Stammverzeichnis der Site stehen?

Die neue Zuordnung lautet wie folgt:

<servlet-mapping>
    <servlet-name>HomeServlet</servlet-name>
    <url-pattern>/HomeServlet</url-pattern>
</servlet-mapping>
Brian DiCasa
quelle
Vielen Dank für Update 2, ich habe ein paar Stunden lang meinen Kopf gegen die Wand geschlagen, um herauszufinden, warum mein CSS nicht geladen wurde. (hatte / als Anmerkung).
Kiwicomb123

Antworten:

100

Alle relativen URLs auf der von der JSP-Datei generierten HTML-Seite beziehen sich auf die aktuelle Anforderungs-URL (die URL, wie Sie in der Adressleiste des Browsers sehen) und nicht wie erwartet auf den Speicherort der JSP-Datei auf der Serverseite. Es ist nämlich der Webbrowser, der diese Ressourcen einzeln per URL herunterladen muss, nicht der Webserver, der sie irgendwie von der Festplatte einbinden muss.

Abgesehen davon, dass die relativen URLs geändert werden, um sie relativ zur URL des Servlets anstelle des Speicherorts der JSP-Datei zu machen, besteht eine andere Möglichkeit, dieses Problem zu beheben, darin, sie relativ zum Domänenstamm zu machen (dh mit a zu beginnen /). Auf diese Weise müssen Sie sich keine Gedanken mehr über das erneute Ändern der relativen Pfade machen, wenn Sie die URL des Servlets ändern.

<head>
    <link rel="stylesheet" href="/context/css/default.css" />
    <script src="/context/js/default.js"></script>
</head>
<body>
    <img src="/context/img/logo.png" />
    <a href="/context/page.jsp">link</a>
    <form action="/context/servlet"><input type="submit" /></form>
</body>

Wahrscheinlich möchten Sie den Kontextpfad jedoch nicht fest codieren. Sehr vernünftig. Den Kontextpfad in EL erhalten Sie über ${pageContext.request.contextPath}.

<head>
    <link rel="stylesheet" href="${pageContext.request.contextPath}/css/default.css" />
    <script src="${pageContext.request.contextPath}/js/default.js"></script>
</head>
<body>
    <img src="${pageContext.request.contextPath}/img/logo.png" />
    <a href="${pageContext.request.contextPath}/page.jsp">link</a>
    <form action="${pageContext.request.contextPath}/servlet"><input type="submit" /></form>
</body>

(die leicht verkürzt <c:set var="root" value="${pageContext.request.contextPath}" />und wie ${root}anderswo verwendet werden kann)

Wenn Sie keine unlesbaren XML- und fehlerhaften XML-Syntaxhervorhebungen befürchten, verwenden Sie JSTL <c:url> :

<head>
    <link rel="stylesheet" href="<c:url value="/css/default.css" />" />
    <script src="<c:url value="/js/default.js" />"></script>
</head>
<body>
    <img src="<c:url value="/img/logo.png" />" />
    <a href="<c:url value="/page.jsp" />">link</a>
    <form action="<c:url value="/servlet" />"><input type="submit" /></form>
</body>

In beiden Fällen ist dies wiederum ziemlich umständlich, wenn Sie viele relative URLs haben. Dafür können Sie das <base>Tag verwenden. Alle relativen URLs werden sofort relativ dazu. Es hat jedoch mit dem System zu starten ( http://, https://usw.). Es gibt keine gute Möglichkeit, den Basiskontextpfad in einfachem EL zu erhalten. Daher benötigen wir hier ein wenig Hilfe von JSTL .

<%@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="uri" value="${req.requestURI}" />
<c:set var="url">${req.requestURL}</c:set>
...
<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="page.jsp">link</a>
    <form action="servlet"><input type="submit" /></form>
</body>

Dies hat wiederum (wieder) einige Einschränkungen. Anker (die #identifierURLs) werden auch relativ zum Basispfad! Sie möchten es stattdessen relativ zur Anforderungs-URL (URI) machen. Also, ändere dich gerne

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

zu

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

Jeder Weg hat seine eigenen Vor- und Nachteile. Es liegt an Ihnen, welche Sie wählen. Zumindest sollten Sie jetzt verstehen, wie dieses Problem verursacht wird und wie Sie es lösen können :)

Siehe auch:

BalusC
quelle
Ich hatte wirklich gehofft, dass dies funktionieren würde, da es sinnvoll ist, aber der Browser kann die Dateien immer noch nicht finden. Ich habe meiner Frage weitere Informationen hinzugefügt (App-Struktur und einige andere allgemeine Informationen). Danke für die Hilfe!
Brian DiCasa
3
Sie haben das Servlet zugeordnet /(Geruch, Geruch;)). Es werden also auch CSS-Dateien abgefangen (tatsächlich jede HTTP-Anforderung). Behandelt es sie richtig? Dh Sie können über localhost direkt im Webbrowser auf die CSS-Datei zugreifen : 8080 / context / styles / default.css ?
BalusC
Nicht, wenn es "/" zugeordnet war. Ich kann, wenn es als "/ HomeServlet" zugeordnet ist.
Brian DiCasa
Ich bin mir nicht sicher, warum Sie es ursprünglich zugeordnet haben /*, aber wenn Sie versuchen, eine Art Front-Controller zu erstellen, würde ich vorschlagen, sich durch diese Antwort und vielleicht auch durch diese Antwort zu bringen .
BalusC
@BalusC - In Ihrem ersten Absatz, in dem Sie sagten: "Es ist nämlich der Webbrowser, der diese Ressourcen einzeln per URL herunterladen muss, nicht der Webserver, der sie irgendwie von der Festplatte einbinden muss." Können wir praktisch überprüfen, ob es in der Verantwortung des Browsers liegt, die Ressourcen und nicht den Webserver abzurufen? Wenn Sie mich auf ein praktisches Beispiel oder Tutorial verweisen können, ist das großartig!
Abhishek Aggarwal
2

Sie müssen die tatsächliche HTML-Ausgabe für den Hinweis analysieren.

Wenn Sie den Pfad wie folgt angeben, bedeutet dies "vom aktuellen Standort". Wenn Sie jedoch mit einem Pfad beginnen /, bedeutet dies "aus dem Kontext".

Adeel Ansari
quelle
Ich bin mir nicht sicher, was du meinst. Wenn ich den CSS-Link dazu
ändere
Ich meine, Sie können die HTML-Quelle in Ihrem Browser anzeigen, um herauszufinden, ob der Pfad richtig ist oder nicht. Wenn dies nicht der Fall ist, was müssen Sie tun, um es zu korrigieren?
Adeel Ansari
Ich habe die Quelle angezeigt und für meine Link-Tags wird das angegeben, was ich in meiner Frage gepostet habe. Ich bin mir nicht sicher, warum die Dateien gefunden werden können, wenn ich direkt auf meinen JSP verweise, und wenn ich eine Weiterleitung mache, können sie nicht gefunden werden. Wo kann ich meine Bilder speichern, damit sie von jedem Ort in der Web-App aus gefunden werden können?
Brian DiCasa
Okay, das liegt daran, dass Sie index.jspsich auf derselben Position / Ebene befinden wie Ihre stylesund imagesVerzeichnisse. Wenn Sie es also direkt index.jspals Begrüßungsdatei verwenden, erscheint alles wie ein Zauber. Wenn Sie andererseits dieselbe Ressource über das Servlet weiterleiten, ist die Angelegenheit nicht mehr dieselbe. [Fortsetzung
folgt
@Brian D.: ... Um eine Anfrage an ein bestimmtes Servlet zu richten, berücksichtigen wir den Pfad nicht. Wir verwenden die Servlet-Zuordnung. Jetzt müssen wir das context pathhier verstehen . Wie Sie in den Dokumenten gesehen haben, /die im Pfad eine bestimmte Bedeutung haben, möchten wir die Anforderung weiterleiten oder die Anforderung umleiten. Ohne den Schrägstrich wird er vom aktuellen Speicherort und nicht vom Kontextpfad übernommen. Ich hoffe du kriegst mich jetzt.
Adeel Ansari
0

Ihre Begrüßungsseite ist als That Servlet festgelegt. Daher sollte der gesamte Pfad für CSS-Bilder relativ zu diesem Servlet-DIR angegeben werden. Das ist eine schlechte Idee! Warum brauchen Sie das Servlet als Homepage? .jsp als Indexseite festlegen und von dort auf eine beliebige Seite umleiten?

Versuchen Sie, Felder aus der Datenbank zu füllen? Verwenden Sie deshalb ein Servlet?

GoodSp33d
quelle
4
Die Verwendung eines Servlets als (MVC) Frontcontroller ist sicherlich keine schlechte Idee.
BalusC
0

Wenn Sie Spring MVC verwenden, müssen Sie das Standardaktionsservlet für statische Inhalte deklarieren. Fügen Sie die folgenden Einträge in spring-action-servlet.xml hinzu. Es hat bei mir funktioniert.

HINWEIS: Bewahren Sie alle statischen Inhalte außerhalb von WEB-INF auf.

<!-- Enable annotation-based controllers using @Controller annotations -->
<bean id="annotationUrlMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
    <property name="order" value="0" />
</bean>

<bean id="controllerClassNameHandlerMapping" class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping">
    <property name="order" value="1" />
</bean>

<bean id="annotationMethodHandlerAdapter" class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
AjayP
quelle
0

Was Ihr Update angeht, war ich verwirrt über die Gründe, die dahinter stecken. Ich habe etwas tiefer gegraben und dieses Juwel gefunden:

  • yourite.com wird zu yoursite.com/
  • yoursite.com/ ist ein Verzeichnis, daher wird die Liste der Begrüßungsdateien gescannt
  • yourite.com/CMS ist die erste Begrüßungsdatei ("CMS" in der Begrüßungsdateiliste), und es gibt eine Zuordnung von / CMS zum MyCMS-Servlet, sodass auf das Servlet zugegriffen werden kann.

Quelle: http://wiki.metawerx.net/wiki/HowToUseAServletAsYourMainWebPage

Das Mapping macht dann also Sinn.

Und man kann jetzt $ {pageContext.request.contextPath} / path / als src / href für relative Links frei verwenden!

Justin Cuaresma
quelle
0

kurze Antwort - fügen Sie die folgende Zeile in den JSP ein, die die Basisbasis definiert.
href = "/ {root Ihrer Anwendung} /"

Ankit Pandoh
quelle
0

Der folgende Code hat bei mir funktioniert.

anstatt <% @ include file = "styles / default.css"%> zu verwenden

Chamika Ravinda
quelle
0

Sie können diesen auch ausprobieren. Weil das bei mir funktioniert hat und es einfach ist.

<style>
    <%@ include file="/css/style.css" %>
</style>
Dulya Perera
quelle