Браузер не может получить доступ / найти относительные ресурсы, такие как 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>

У каждого способа есть свои плюсы и минусы. Что выбирать - решать вам. По крайней мере, теперь вы должны понимать, чем вызвана эта проблема и как ее решить :)

Смотрите также:

BalusC
источник
Я действительно надеялся, что это сработает, поскольку это имеет смысл, но браузер все еще не может найти файлы. Я добавил дополнительную информацию к своему вопросу (структура приложения и другая общая информация). Спасибо за помощь!
Брайан ДиКаса,
3
Вы нанесли сервлет на карту /(запах, запах;)). Таким образом, он также перехватывает файлы CSS (фактически каждый HTTP-запрос). Правильно ли он обращается с ними? Т.е. вы можете получить доступ к файлу CSS прямо в веб-браузере с помощью localhost: 8080 / context / styles / default.css ?
BalusC
Не тогда, когда он был сопоставлен с "/". Я могу, когда он отображается как «/ HomeServlet».
Брайан ДиКаса,
Я не уверен, почему вы изначально сопоставили его /*, но если вы пытаетесь создать своего рода фронт-контроллер, я бы предложил пройти через этот ответ, а может быть, и этот ответ .
BalusC
@BalusC - В первом абзаце, где вы сказали: «Именно веб-браузер должен загружать эти ресурсы индивидуально по URL-адресу, а не веб-сервер, который должен каким-то образом включать их с диска». Можем ли мы проверить на практике, что за получение ресурсов отвечает браузер, а не веб-сервер? Если вы можете указать мне на какой-нибудь практический пример или учебник, это будет здорово!
Абхишек Аггарвал
2

Чтобы получить подсказку, вы должны проанализировать фактический вывод HTML.

Указание такого пути означает «из текущего местоположения», с другой стороны, если вы начнете с, это /будет означать «из контекста».

Адил Ансари
источник
Я не понимаю, что вы имеете в виду. Если я изменю ссылку css на это:
Брайан ДиКаса,
Я имею в виду, что вы можете просмотреть исходный HTML-код из своего браузера, чтобы узнать, правильный путь или нет. Если это не так, что вам нужно сделать, чтобы исправить это.
Адил Ансари
Я просматривал исходный код, и мои теги ссылок были опубликованы в моем вопросе. Думаю, я не уверен, почему, если я ссылаюсь непосредственно на свой jsp, файлы можно найти, а если я сделаю пересылку, их нельзя будет найти? Где я могу хранить свои изображения, чтобы их можно было найти из любого места в веб-приложении?
Брайан ДиКаса,
Хорошо, это происходит потому , что ваш index.jspнаходится на том же месте / уровня , как ваши stylesи imagesкаталоги. Поэтому, когда вы напрямую используете index.jspкак приветственный файл, все выглядит как шарм. С другой стороны, когда вы перенаправляете тот же ресурс через сервлет, дело уже не то же самое. [продолжение следует ...]
Адил Ансари 07
@Brian D .: ... Чтобы направить запрос к определенному сервлету, мы не учитываем путь, мы используем отображение сервлета. Теперь мы должны понять context pathздесь. Как вы видели в документации, это /имеет определенное значение при использовании в пути, который мы хотим перенаправить или перенаправить запрос. Без косой черты он будет взят из текущего местоположения, а не из контекстного пути. Надеюсь, теперь ты меня понимаешь.
Адил Ансари,
0

Ваша страница приветствия установлена ​​как That Servlet. Таким образом, все css, пути к изображениям должны быть указаны относительно этого сервлета DIR. что плохая идея! зачем вам сервлет в качестве домашней страницы? установить .jsp в качестве индексной страницы и перенаправить оттуда на любую страницу?

вы пытаетесь заполнить какие-либо поля из базы данных, поэтому вы используете сервлет?

GoodSp33d
источник
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"/>
AjayP
источник
0

Что касается вашего обновления, я был сбит с толку рассуждениями, стоящими за ним. Покопавшись немного глубже, я нашел этот драгоценный камень:

  • yoursite.com становится yoursite.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

Код ниже работал у меня.

вместо использования <% @ include file = "styles / default.css"%>

Чамика Равинда
источник
0

Вы можете попробовать и этот. Потому что это сработало для меня, и это просто.

<style>
    <%@ include file="/css/style.css" %>
</style>
Дуля Перера
источник