调用转发到JSP的Servlet时,浏览器无法访问/查找CSS,图像和链接等相关资源


82

当我将servlet转发到JSP时,我在加载CSS和图像以及创建指向其他页面的链接时遇到了麻烦。具体而言,当我把我的<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-fileweb.xml

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

Servlet声明和映射如下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:我终于找到了问题-我的servlet映射不正确。显然,在将Servlet设置为您的Servlet时,<welcome-file>它不能具有的URL模式/,我觉得这很奇怪,因为那不代表网站的根目录吗?

新的映射如下:

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

感谢您提供更新2,一直将我的头撞在墙上两个小时,试图弄清为什么CSS无法加载。(有/作为注释)。
kiwicomb123

Answers:


100

JSP文件生成的HTML页面中的所有相对URL都相对于当前请求URL(如您在浏览器地址栏中看到的URL),而不是您所期望的相对于服务器端JSP文件的位置。是Web浏览器必须通过URL单独下载这些资源,而不是Web服务器必须以某种方式从磁盘包括这些资源。

除了更改相对URL以使其相对于servlet的URL而不是JSP文件的位置之外,另一种解决此问题的方法是使它们相对于域根(即以开头/)。这样,您无需担心在更改servlet的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都将立即成为相对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 2010年

3
您已将servlet映射到/(气味,气味;))。因此,它也会拦截CSS文件(实际上是每个HTTP请求)。处理正确吗?即您可以通过localhost:8080 / context / styles / default.css在webbrowser中直接访问CSS文件?
BalusC

不是当它映射到“ /”时。我可以将它映射为“ / HomeServlet”。
Brian DiCasa 2010年

我不确定您为什么最初将其映射到该对象上/*,但是如果您尝试创建一种前端控制器,则建议您自己通过此答案,也许也可以通过此答案
BalusC

@BalusC-在您的第一段中,您说:“是Web浏览器必须通过URL单独下载这些资源,而不是Web服务器必须以某种方式从磁盘包括这些资源。” 我们是否可以实际上检查浏览器是否负责获取资源而不是Web服务器?如果您能指出一些实际的例子或教程,那将是很棒的!
阿比舍克·阿格加瓦尔


2

您必须分析实际的HTML输出,以获取提示。

给出这样的路径表示“来自当前位置”,而如果您以a开头则/表示“来自上下文”。


我不确定你的意思。如果我将CSS链接更改为此:
Brian DiCasa 2010年

我的意思是,您可以从浏览器查看HTML源代码,以查明路径是否正确。如果不是,那么您需要做什么才能使其正确。
阿德·安萨里

我一直在查看源代码,链接标签的内容就是我在问题中发布的内容。我想我不确定为什么如果直接链接到我的jsp,可以找到这些文件,而如果进行转发,则找不到它们?我可以在哪里存储图像,以便可以在Web应用程序中的任何位置找到它们?
Brian DiCasa 2010年

好吧,那是因为你index.jsp是在相同的位置/水平,你stylesimages目录是。因此,当您直接将其index.jsp用作欢迎文件时,所有内容看起来都像是魅力。另一方面,当您通过Servlet转发相同的资源时,事情就不再相同了。[待续...]
Adeel Ansari 2010年

@Brian D .: ...为了将请求定向到特定的servlet,我们不考虑路径,我们使用servlet映射。现在,我们必须了解context path这里。正如您在文档中所看到的那样,/当在路径中使用它时,我们要转发请求或重定向请求。如果没有斜杠,它将从当前位置获取,而不是从上下文路径获取。我希望你现在能得到我。
Adeel Ansari'9

0

您的欢迎页面设置为That Servlet。因此,应相对于该servlet DIR给出所有的CSS,图像路径。这是一个坏主意!为什么需要将servlet作为主页?将.jsp设置为索引页面并从那里重定向到任何页面?

您是否要填充db中的任何字段,这就是为什么要使用servlet?


4
使用servlet作为(MVC)前端控制器当然不是一个坏主意。
BalusC 2010年

0

如果您使用的是Spring MVC,则需要声明静态内容的默认操作servlet。在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

至于您的更新,我对背后的原因感到困惑。深入研究发现以下宝石:

  • yoursite.com变成yoursite.com/
  • yoursite.com/是目录,因此将扫描welcome-file-list
  • yoursite.com/CMS是第一个欢迎文件(welcome-file-list中的“ CMS”),并且/ CMS映射到MyCMS servlet,因此可以访问该servlet。

来源:http//wiki.metawerx.net/wiki/HowToUseAServletAsYourMainWebPage

因此,映射确实有意义。

现在,您可以自由使用$ {pageContext.request.contextPath} / path /作为src / href的相对链接!




By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.