Браузер не може отримати доступ / знайти відносні ресурси, такі як CSS, зображення та посилання під час виклику сервлета, який переадресовує на JSP


83

У мене виникають проблеми із завантаженням CSS та зображень та створенням посилань на інші сторінки, коли сервлет пересилається до JSP. Зокрема, коли я встановлюю <welcome-file>значення index.jsp, завантажується CSS і відображаються мої зображення. Однак, якщо я встановив, <welcome-file>для HomeServletякого переадресації керування index.jsp, CSS не застосовується, а мої зображення не відображаються.

Мій файл CSS знаходиться у web/styles/default.css.
Мої зображення в web/images/.

Я посилаюся на свій CSS так:

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

Я відображаю свої зображення таким чином:

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

Як спричинена ця проблема та як я можу її вирішити?


Оновлення 1 : Я додав структуру програми, а також деяку іншу інформацію, яка може допомогти.

текст заміщення

header.jspФайл це файл , який містить посилання тег для CSS. HomeServletВстановлюється як мій welcome-fileін web.xml:

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

Сервлет оголошується та відображається наступним чином у 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>

Оновлення 2 : нарешті я знайшов проблему - мій сервлет був неправильно зіставлений. Очевидно, коли ви встановлюєте сервлет як свій, <welcome-file>він не може мати шаблон URL-адреси /, що мені здається дивним, бо це не означає кореневий каталог сайту?

Нове відображення таке:

<servlet-mapping>
    <servlet-name>HomeServlet</servlet-name>
    <url-pattern>/HomeServlet</url-pattern>
</servlet-mapping>

Дякую за оновлення 2, я пару годин бився головою об стіну, намагаючись зрозуміти, чому мій css не завантажувався. (мав / як анотацію).
kiwicomb123

Відповіді:


101

Усі відносні URL-адреси на сторінці HTML, створені файлом JSP, відносяться до поточної URL-адреси запиту (URL-адреси, як ви бачите в адресному рядку браузера), а не до розташування файлу JSP на стороні сервера, як ви очікуєте. А саме веб-браузер повинен завантажувати ці ресурси окремо за URL-адресою, а не веб-сервер, який повинен якось включати їх з диска.

Окрім зміни відносних URL-адрес, щоб зробити їх відносно URL-адреси сервлету замість розташування файлу JSP, інший спосіб вирішити цю проблему - зробити їх відносно кореня домену (тобто почати з a /). Таким чином, вам не потрібно турбуватися про те, щоб ще раз змінити відносні шляхи, коли ви змінюєте URL-адресу сервлету.

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

Однак ви, мабуть, хотіли б не жорстко кодувати шлях контексту. Дуже розумно. Ви можете отримати шлях до контексту в EL за допомогою ${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>

(який можна легко скоротити <c:set var="root" value="${pageContext.request.contextPath}" />та використовувати як ${root}будь-де)

Або, якщо ви не боїтесь нечитабельного XML та підсвічування синтаксису XML, використовуйте 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>

У будь-якому випадку, це, в свою чергу, досить громіздке, якщо у вас багато відносних URL-адрес. Для цього ви можете використовувати <base>тег. Усі відносні URL-адреси миттєво стануть відносно них. Однак вона має почати зі схемою ( http://, https://і т.д.). Немає акуратного способу отримати базовий шлях контексту в простому EL, тому нам потрібна невелика допомога 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>

Це, в свою чергу, (знову ж таки) має деякі застереження. Якорі ( #identifierURL-адреси) також стануть відносно базового шляху! Натомість ви хотіли б зробити це відносно URL-адреси запиту (URI). Отже, міняйте лайк

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

до

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

Кожен спосіб має свої плюси і мінуси. Вибирати, вирішувати вам. Принаймні, ви тепер повинні розуміти, як ця проблема виникла і як її вирішити :)

Дивитися також:


Я справді сподівався, що це спрацює, оскільки це має сенс, але браузер все ще не може знайти файли. Я додав трохи більше інформації до свого запитання (структура програми та інша загальна інформація). Дякую за допомогу!
Brian DiCasa

3
Ви нанесли на карту сервлет /(запах, запах;)). Тому він також перехоплює файли CSS (фактично кожен HTTP-запит). Це правильно з ними поводиться? Тобто ви можете отримати доступ до файлу CSS безпосередньо у веб-браузері за допомогою localhost: 8080 / context / styles / default.css ?
BalusC

Не тоді, коли він був зіставлений з "/". Я можу, коли він відображається як "/ HomeServlet".
Brian DiCasa

Я не впевнений, чому ви спочатку його нанесли на карту /*, але якщо ви намагаєтеся створити якийсь фронтальний контролер, я б запропонував пройти цю відповідь, а можливо, і цю відповідь .
BalusC

@BalusC - У вашому першому абзаці, де ви сказали: "Саме веб-браузер повинен завантажувати ці ресурси окремо за URL-адресою, а не веб-сервер, який повинен якось включати їх з диска". Чи можемо ми практично перевірити, що браузер несе відповідальність за отримання ресурсів, а не веб-сервер? Якщо ви можете вказати мені якийсь практичний приклад чи підручник, це буде чудово!
Абхішек Аггарвал,


2

Для підказки ви повинні проаналізувати фактичний вихідний файл HTML.

Якщо вказати такий шлях, це означає "з поточного місцезнаходження", з іншого боку, якщо ви починаєте з того, /що означало б "із контексту".


Я не впевнений, що ви маєте на увазі. Якщо я зміню посилання css на це:
Брайан ДіКаса

Я маю на увазі, що ви можете переглянути HTML-джерело з вашого браузера, щоб з’ясувати, чи правильний шлях чи ні. Якщо це не так, що потрібно зробити, щоб зробити це правильно.
Adeel Ansari

Я переглядав джерело, і для моїх тегів посилань з’являється те, що я розмістив у своєму запитанні. Я думаю, я не впевнений, чому, якщо я посилаюся безпосередньо на свій jsp, що файли можна знайти, а якщо я перенаправляю, їх неможливо знайти? Де я можу зберігати свої зображення, щоб їх можна було знайти з будь-якого місця у веб-програмі?
Brian DiCasa

Гаразд, це тому, що ваш файл index.jspзнаходиться на тому самому місці / рівні, що і ваш, stylesі imagesкаталоги. Тому, коли ви безпосередньо використовуєте index.jspяк файл привітання, все виглядає як шарм. З іншого боку, коли ви пересилаєте той самий ресурс через сервлет, справа вже не однакова. [продовження ...]
Адель Ансарі

@Brian D .: ... Щоб направити запит до певного сервлету, який ми не враховуємо, шлях, ми використовуємо відображення сервлетів. Тепер ми повинні зрозуміти context pathтут. Як ви бачили в документах, що /має певне значення при використанні в шляху, до якого ми хочемо переслати запит або перенаправити запит. Без косої риски вона буде взята з поточного розташування, а не з контекстного шляху. Сподіваюся, ти зараз мене отримаєш.
Adeel Ansari

0

Ваша привітальна сторінка встановлена ​​як Цей сервлет. Отже, весь шлях css, images повинен бути вказаний відносно цього DIR сервлета. що погана ідея! навіщо вам потрібен сервлет як домашня сторінка? встановити .jsp як сторінку індексу та перенаправити на будь-яку сторінку звідти?

ви намагаєтеся заповнити будь-які поля з db, тому ви використовуєте сервлет?


4
Використання сервлета як фронтального контролера (MVC), безумовно, не погана ідея.
BalusC

0

Якщо ви використовуєте Spring MVC, то вам потрібно оголосити сервлет дій за замовчуванням для статичного вмісту. Додайте такі записи у spring-action-servlet.xml. У мене це спрацювало.

ПРИМІТКА: зберігайте весь статичний вміст поза 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"/>

0

Що стосується вашого оновлення, я був збентежений за міркування позаду. Викопав трохи глибше і знайшов цей камінь:

  • yourite.com стає вашимitesite.com/
  • yoursite.com/ - це каталог, тому список вітальних файлів сканується
  • yoursite.com/CMS - це перший файл привітання ("CMS" у списку файлів привітання), і існує зіставлення / CMS із сервлетом MyCMS, щоб отримати доступ до сервлету.

Джерело: http://wiki.metawerx.net/wiki/HowToUseAServletAsYourMainWebPage

Отже, відображення тоді має сенс.

І тепер можна вільно використовувати $ {pageContext.request.contextPath} / path / як src / href для відносних посилань!


0

коротка відповідь - додайте в jsp наступний рядок, який визначатиме базову
базу href = "/ {корінь вашої програми} /"



0

Ви можете спробувати і цей, а також. Тому що це працювало для мене, і це просто.

<style>
    <%@ include file="/css/style.css" %>
</style>
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.