Przeglądarka nie może uzyskać dostępu / znaleźć względnych zasobów, takich jak CSS, obrazy i łącza, podczas wywoływania serwletu, który przekazuje do strony JSP

83

Mam problem z ładowaniem CSS i obrazów oraz tworzeniem odsyłaczy do innych stron, gdy mam aplet przekazujący do strony JSP. W szczególności, kiedy ustawię <welcome-file>na index.jsp, CSS jest ładowany, a moje obrazy są wyświetlane. Jeśli jednak ustawię opcję, <welcome-file>do HomeServletktórej przekazuje sterowanie index.jsp, CSS nie jest stosowany, a moje obrazy nie są wyświetlane.

Mój plik CSS jest w formacie web/styles/default.css.
Moje obrazy są w formacie web/images/.

Łączę się z moim CSS w ten sposób:

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

Wyświetlam moje obrazy w następujący sposób:

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

Skąd się bierze ten problem i jak mogę go rozwiązać?


Aktualizacja 1 : Dodałem strukturę aplikacji, a także kilka innych informacji, które mogą pomóc.

tekst alternatywny

header.jspPlik jest plikiem, który zawiera znacznik link do CSS. HomeServletJest ustawiony jako mój welcome-filein web.xml:

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

Aplet jest deklarowany i mapowany w następujący sposób w 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>

Aktualizacja 2 : W końcu znalazłem problem - mój serwlet został nieprawidłowo zmapowany. Najwyraźniej ustawiając serwlet jako swój, <welcome-file>nie może mieć wzorca adresu URL /, co wydaje mi się trochę dziwne, ponieważ czy nie oznaczałoby to katalogu głównego witryny?

Nowe mapowanie wygląda następująco:

<servlet-mapping>
    <servlet-name>HomeServlet</servlet-name>
    <url-pattern>/HomeServlet</url-pattern>
</servlet-mapping>
Brian DiCasa
źródło
Dziękuję za aktualizację 2, przez kilka godzin waliłem głową w ścianę, próbując dowiedzieć się, dlaczego mój css się nie ładuje. (miał / jako adnotacja).
kiwicomb123

Odpowiedzi:

101

Wszystkie względne adresy URL na stronie HTML wygenerowanej przez plik JSP odnoszą się do adresu URL bieżącego żądania (adresu URL widocznego na pasku adresu przeglądarki), a nie do lokalizacji pliku JSP po stronie serwera, jak można się spodziewać. Mianowicie przeglądarka internetowa musi pobierać te zasoby indywidualnie przez adres URL, a nie serwer sieciowy, który musi je w jakiś sposób dołączyć z dysku.

Oprócz zmiany względnych adresów URL, tak aby były względne w stosunku do adresu URL serwletu zamiast lokalizacji pliku JSP, innym sposobem rozwiązania tego problemu jest ustawienie ich względem katalogu głównego domeny (tj. Rozpoczynanie się od a /). W ten sposób nie musisz martwić się o zmianę ścieżek względnych po raz kolejny, gdy zmienisz adres URL serwletu.

<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>

Jednak prawdopodobnie nie chciałbyś zakodować na stałe ścieżki kontekstu. Bardzo rozsądne. Ścieżkę kontekstu w EL można uzyskać przez ${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>

(które można łatwo skrócić <c:set var="root" value="${pageContext.request.contextPath}" />i używać jak ${root}gdzie indziej)

Lub, jeśli nie boisz się nieczytelnego XML i zepsutego podświetlania składni XML, użyj 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>

Tak czy inaczej, jest to z kolei dość kłopotliwe, jeśli masz dużo względnych adresów URL. Do tego możesz użyć <base>tagu. Wszystkie względne adresy URL natychmiast staną się względem niego względne. Ma jednak na początek programu ( http://, https://itp). Nie ma fajnego sposobu na uzyskanie podstawowej ścieżki kontekstu w zwykłym EL, więc potrzebujemy tutaj niewielkiej pomocy 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>

To z kolei (ponownie) ma pewne zastrzeżenia. Kotwice ( #identifieradresy URL) również staną się względne w stosunku do ścieżki podstawowej! Zamiast tego chciałbyś, aby był względny w stosunku do adresu URL żądania (URI). Więc zmień się jak

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

do

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

Każdy sposób ma swoje wady i zalety. Wybór należy do Ciebie. Przynajmniej powinieneś teraz zrozumieć, dlaczego ten problem jest spowodowany i jak go rozwiązać :)

Zobacz też:

BalusC
źródło
Naprawdę miałem nadzieję, że to zadziała tak, jak ma to sens, ale przeglądarka nadal nie może zlokalizować plików. Dodałem więcej informacji do mojego pytania (struktura aplikacji i inne ogólne informacje). Dzięki za pomoc!
Brian DiCasa,
3
Zmapowałeś serwlet na /(zapach, zapach;)). Więc przechwytuje również pliki CSS (w rzeczywistości każde żądanie HTTP). Czy prawidłowo je obsługuje? Oznacza to, że możesz uzyskać dostęp do pliku CSS bezpośrednio w przeglądarce internetowej przez localhost: 8080 / context / styles / default.css ?
BalusC,
Nie wtedy, gdy został zmapowany do „/”. Mogę jednak, gdy jest mapowany jako „/ HomeServlet”.
Brian DiCasa,
Nie jestem pewien, dlaczego początkowo go odwzorowałeś /*, ale jeśli próbujesz stworzyć rodzaj kontrolera frontowego, sugerowałbym przejrzenie tej odpowiedzi, a może także tej odpowiedzi .
BalusC,
@BalusC - W pierwszym akapicie, w którym powiedziałeś: „To jest przeglądarka internetowa, która musi pobierać te zasoby indywidualnie za pomocą adresu URL, a nie serwer sieciowy, który musi je w jakiś sposób dołączyć z dysku”. Czy możemy praktycznie sprawdzić, czy za pobieranie zasobów odpowiada przeglądarka, a nie serwer WWW? Jeśli możesz wskazać mi jakiś praktyczny przykład lub tutorial, który będzie świetny!
Abhishek Aggarwal
2

Aby uzyskać wskazówkę, musisz przeanalizować rzeczywisty wynik HTML.

Podanie takiej ścieżki oznacza „z bieżącej lokalizacji”, z drugiej strony, jeśli zaczniesz od /, oznaczałoby to „z kontekstu”.

Adeel Ansari
źródło
Nie jestem pewien, co masz na myśli. Jeśli zmienię link css na ten:
Brian DiCasa
Mam na myśli to, że możesz wyświetlić źródło HTML w przeglądarce, aby dowiedzieć się, czy ścieżka jest prawidłowa, czy nie. Jeśli tak nie jest, co należy zrobić, aby było poprawne.
Adeel Ansari,
Przeglądałem źródło i to, co pojawia się w przypadku moich tagów linków, jest tym, co zamieściłem w moim pytaniu. Wydaje mi się, że nie jestem pewien, dlaczego, jeśli łączę się bezpośrednio z moim jsp, że pliki można znaleźć, a jeśli zrobię dalej, nie można ich znaleźć? Gdzie mogę przechowywać moje obrazy, aby można je było znaleźć z dowolnego miejsca w aplikacji internetowej?
Brian DiCasa,
Okej, to dlatego, że znajdujesz się index.jspw tej samej lokalizacji / na tym samym poziomie co Twoje stylesi imageskatalogi. Dlatego, gdy używasz bezpośrednio index.jspjako pliku powitalnego, wszystko wygląda jak urok. Z drugiej strony, gdy przekazujesz dalej ten sam zasób przez serwlet, sprawa nie jest już taka sama. [ciąg dalszy…]
Adeel Ansari,
@Brian D .: ... Aby skierować żądanie do konkretnego serwletu, nie bierzemy pod uwagę ścieżki, używamy mapowania serwletów. Teraz musimy zrozumieć context pathtutaj. Jak widzieliście w dokumentach, które /mają określone znaczenie, gdy są używane w ścieżce, w której chcemy przekazać żądanie lub przekierować żądanie. Bez ukośnika zostanie pobrany z bieżącej lokalizacji, a nie ze ścieżki kontekstu. Mam nadzieję, że teraz mnie rozumiesz.
Adeel Ansari,
0

Twoja strona powitalna jest ustawiona jako That Servlet. Zatem wszystkie ścieżki css, obrazy powinny być podawane względem tego serwletu DIR. co jest złym pomysłem! dlaczego potrzebujesz serwletu jako strony domowej? ustawić .jsp jako stronę indeksową i przekierowywać do dowolnej strony stamtąd?

czy próbujesz wypełnić jakiekolwiek pola z bazy danych, czy dlatego używasz serwletu?

GoodSp33d
źródło
4
Używanie serwletu jako kontrolera frontowego (MVC) z pewnością nie jest złym pomysłem.
BalusC,
0

Jeśli używasz Spring MVC, musisz zadeklarować domyślny serwlet akcji dla zawartości statycznej. Dodaj następujące wpisy w spring-action-servlet.xml. U mnie to zadziałało.

UWAGA: przechowuj całą statyczną zawartość poza WEB-INF.

<!-- 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
źródło
0

Jeśli chodzi o twoją aktualizację, byłem zdezorientowany co do uzasadnienia. Kopałem trochę głębiej i znalazłem ten klejnot:

  • twoja_witryna.com staje się twojastrona.com/
  • twoja_witryna.com/ to katalog, więc lista plików-powitalnych jest skanowana
  • twoja_witryna.com/CMS jest pierwszym plikiem powitalnym („CMS” na liście plików-powitalnych) i istnieje mapowanie / CMS do serwletu MyCMS, dzięki czemu serwlet jest dostępny.

Źródło: http://wiki.metawerx.net/wiki/HowToUseAServletAsYourMainWebPage

Zatem mapowanie ma sens.

I można teraz swobodnie używać $ {pageContext.request.contextPath} / path / jako src / href dla linków względnych!

Justin Cuaresma
źródło
0

krótka odpowiedź - dodaj następujący wiersz w pliku jsp, który zdefiniuje podstawową
podstawę href = "/ {root twojej aplikacji} /"

Ankit Pandoh
źródło
0

Poniższy kod zadziałał dla mnie.

zamiast używać <% @ include file = "styles / default.css"%>

Chamika Ravinda
źródło
0

Możesz również wypróbować ten. Ponieważ to zadziałało i jest proste.

<style>
    <%@ include file="/css/style.css" %>
</style>
Dulya Perera
źródło