ChatGPT解决这个技术问题 Extra ChatGPT

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

当我将 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:我添加了应用程序的结构,以及其他一些可能有帮助的信息。

https://i.stack.imgur.com/nf0zO.png

header.jsp 文件是包含 CSS 链接标记的文件。 HomeServletweb.xml 中设置为我的 welcome-file

<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 设置为您的 <welcome-file> 时,它不能有 / 的 URL 模式,我觉得这有点奇怪,因为那不代表站点的根目录吗?

新映射如下:

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

C
Community

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

除了更改相对 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>

但是,您可能不希望对上下文路径进行硬编码。很合理。您可以通过 ${pageContext.request.contextPath} 获取 EL 中的上下文路径。

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

这反过来又(再次)有一些警告。锚点(#identifier URL)也将相对于基本路径!您希望将其设置为相对于请求 URL (URI)。所以,改变像

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

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

每种方式都有其优点和缺点。由您决定选择哪个。至少,您现在应该了解这个问题是如何引起的以及如何解决它 :)

也可以看看:

是否推荐使用 html 标签?


我真的希望这能正常工作,但浏览器仍然无法找到文件。我在我的问题中添加了更多信息(应用程序结构和其他一些一般信息)。谢谢您的帮助!
您已将 servlet 映射到 /(气味,气味;))。所以它也会拦截 CSS 文件(实际上是每个 HTTP 请求)。是否正确处理它们?即您可以通过 localhost:8080/context/styles/default.css 直接在 webbrowser 中访问 CSS 文件吗?
不是当它映射到“/”时。不过,当它被映射为“/ HomeServlet”时,我可以。
我不知道您为什么最初将它映射到 /*,但如果您尝试创建某种前端控制器,我建议您通过 this answer,也许还可以通过 this answer
@BalusC - 在您的第一段中,您说“这是必须通过 URL 单独下载这些资源的网络浏览器,而不是必须以某种方式从磁盘包含它们的网络服务器。”我们可以实际检查一下,获取资源是浏览器而不是网络服务器的责任吗?如果您能指出一些实用的示例或教程,那就太好了!
l
lennon310

我在 Spring MVC 应用程序中遇到了类似的问题。我使用 < mvc:resources > 标记来解决此问题。

请在以下链接中找到更多详细信息。

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


A
Adeel Ansari

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

通过给出这样的路径意味着“从当前位置”,另一方面,如果您以 / 开头,则意味着“从上下文”。


我不确定你的意思。如果我将 css 链接更改为此:
我的意思是您可以从浏览器查看 HTML 源代码,以确定路径是否正确。如果不是,您需要做什么才能使其正确。
我一直在查看源代码,我的链接标签出现的是我在问题中发布的内容。我想我不确定为什么如果我直接链接到我的 jsp,可以找到文件,如果我进行转发,则找不到它们?我可以在哪里存储我的图像,以便可以从 Web 应用程序的任何位置找到它们?
好的,这是因为您的 index.jsp 与您的 stylesimages 目录位于同一位置/级别。因此,当您直接使用 index.jsp 作为欢迎文件时,一切看起来都像魅力。另一方面,当您通过 servlet 转发相同的资源时,情况就不同了。 [未完待续...]
@Brian D.:...为了将请求定向到我们不考虑路径的特定 servlet,我们使用 servlet 映射。现在,我们必须了解这里的context path。正如您在文档中看到的那样,/ 在我们要转发请求或重定向请求的路径中使用时具有某些特定含义。如果没有斜线,它将取自当前位置,而不是上下文路径。我希望你现在得到我。
G
GoodSp33d

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

您是否尝试从 db 填充任何字段,这就是您使用 servlet 的原因吗?


使用 servlet 作为 (MVC) 前端控制器当然不是一个坏主意。
A
AjayP

如果您使用的是 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"/>

j
jruizaranguren

至于您的更新,我对背后的原因感到困惑。深入挖掘并发现了这个宝石:

yoursite.com 变成 yoursite.com/

yoursite.com/ 是一个目录,所以会扫描welcome-file-list

yoursite.com/CMS 是第一个欢迎文件(欢迎文件列表中的“CMS”),并且有 /CMS 到 MyCMS servlet 的映射,以便访问 servlet。

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

因此,映射确实有意义。

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


A
Ankit Pandoh

简短的回答 - 在 jsp 中添加以下行,它将定义基本的 base href="/{root of your application}/"


C
Chamika Ravinda

下面的代码对我有用。

而不是使用 <%@ include file="styles/default.css"%>


D
Dulya Perera

你也可以试试这个。因为这对我有用,而且很简单。

<style>
    <%@ include file="/css/style.css" %>
</style>

关注公众号,不定期副业成功案例分享
关注公众号

不定期副业成功案例分享

领先一步获取最新的外包任务吗?

立即订阅