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

У меня возникают проблемы с загрузкой 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. Я добавил структуру приложения, а также другую информацию, которая может помочь.

alt text

Файл header.jsp - это файл, содержащий тег ссылки для CSS. HomeServlet устанавливается как my 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>

Ответ 1

Все относительные URL-адреса на странице HTML, сгенерированные JSP файлом, относятся к текущему URL-адресу запроса (URL-адрес, который вы видите в адресной строке браузера) и не, к местоположению файла JSP на стороне сервера, как вы, кажется, ожидаете. Это именно веб-браузер, который должен загружать эти ресурсы по URL-адресу, а не веб-серверу, который должен каким-то образом включить их с диска.

Помимо изменения относительных URL-адресов, чтобы сделать их относительно URL-адреса сервлета вместо местоположения JSP файла, другой способ исправить эту проблему - сделать их относительно корня домена (т.е. начать с /). Таким образом, вам не нужно беспокоиться об изменении относительных путей еще раз при изменении 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>

Это в свою очередь (опять же) некоторые предостережения. Якоря (URL #identifier) также будут относиться к базовому пути! Вы хотели бы сделать это относительно URL-адреса запроса (URI). Итак, измените, например,

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

к

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

Каждый путь имеет свои плюсы и минусы. Это вам решать. По крайней мере, теперь вы должны понять, как эта проблема возникает и как ее решить:)

См. также:

Ответ 2

Я столкнулся с аналогичной проблемой с приложением Spring MVC. Я использовал тег < mvc:resources >, чтобы решить эту проблему.

Пожалуйста, найдите следующую ссылку, содержащую более подробную информацию.

http://www.mkyong.com/spring-mvc/spring-mvc-how-to-include-js-or-css-files-in-a-jsp-page/

Ответ 3

Вы должны проанализировать фактический вывод HTML для подсказки.

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

Ответ 4

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

Вы пытаетесь заполнить любые поля из db, поэтому вы используете сервлет?

Ответ 5

Если вы используете 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"/>

Ответ 6

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

  • yoursite.com становится вашим сайтом /
  • yoursite.com/- это каталог, поэтому проверяется список приветственных файлов
  • yoursite.com/CMS - это первый приветственный файл ( "CMS" в списке приветственных файлов), и есть сопоставление /CMS с сервлетом MyCMS, так что к сервлету обращаются.

Источник: http://wiki.metawerx.net/wiki/HowToUseAServletAsYourMainWebPage

Итак, отображение тогда имеет смысл.

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

Ответ 7

короткий ответ - добавьте следующую строку в jsp, которая определит базу base href= "/{корень вашего приложения}/"