我向项目添加了外部CSS样式表,并将其放置在Eclipse中项目的WEB- CONTENTS文件夹中。当我在Tomcat上部署它时,没有应用样式表。当我在Chrome中调试并打开它时,出现了404 file not found错误。为什么会这样以及如何解决呢?
404 file not found
这是代码:
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>joined now </title> <link href="globalCSS.css" rel="stylesheet" type="text/css"/> </head> <body> <div>this is at the top</div> <c:import url="header.jsp" /> <c:import url="navigationBar.jsp" /> <c:import url="leftpane.jsp" /> <c:import url="mainContent.jsp" /> <c:import url="rightpane.jsp" /> <c:import url="footer.jsp" /> </body> </html>
404 File Not Found出现错误的原因是,作为href属性值的CSS 路径 缺少 context path 。
404 File Not Found
href
HTTP请求URL包含以下部分:
http://[host]:[port][request-path]?[query-string]
的 请求路径 还由以下元素组成:
上下文路径 :正斜杠(/)与Servlet Web应用程序的 上下文根 的串联。例:http://host[:port]/context-root[/url-pattern]
http://host[:port]/context-root[/url-pattern]
Servlet path :与激活该请求的组件别名相对应的path部分。此路径以正斜杠(/)开头。
路径信息 :请求路径的一部分,不是上下文路径或servlet路径的一部分。
在这里阅读更多。
有几种解决问题的方法,以下是其中一些:
<c:url>
在我的Java Web应用程序中<c:url>,当定义CSS / JavaScript /image和其他静态资源的路径时,通常使用JSTL中的 tag 。这样,您可以确保 始终相对于应用程序上下文 (上下文路径)引用这些资源。
如果您说您的CSS位于 WebContent 文件夹中,那么这应该可以工作:
<link type="text/css" rel="stylesheet" href="<c:url value="/globalCSS.css" />" />
它起作用的原因在“ JavaServer Pages™标准标记库 ”版本1.2 规范第7.5章中进行了说明(重点是我的):
7.5 使用适当的重写规则构建URL。 … 该URL必须是以方案开头的绝对URL(例如“ http:// server / context / page.jsp”)或JSP.2.2.1“相对URL规范”中JSP 1.2定义的相对URL。 ”。结果,实现必须 在上下文路径之前添加以斜杠开头的URL (例如“ /page2.jsp”),以便客户端浏览器可以正确解释此类URL。
注意 不要忘记在JSP中使用 _Taglib指令_来引用JSTL标签。
一种 替代 解决方案是使用表达式语言(EL)添加应用程序上下文:
<link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath}/globalCSS.css" />
在这里,我们从 请求 对象中检索了上下文路径。为了访问请求对象,我们使用了 pageContext 隐式对象 。
<c:set>
免责声明 此解决方案的想法来自此处。
为了使访问上下文路径比在解决方案2中更紧凑,您可以首先使用JSTL <c:set>标记,该标记在任何JSP范围(页面,请求,会话)中设置 EL变量的值或EL变量的属性。 ,或应用程序)以供以后访问。
<c:set var="root" value="${pageContext.request.contextPath}"/> ... <link type="text/css" rel="stylesheet" href="${root}/globalCSS.css" />
重要提示 默认情况下,为了设置这样的方式可变,包含此的JSP 组 标签必须访问 至少一次 (包括在设定值的情况下, 应用程序 使用范围 范围 属性,像<c:set var="foo" value="bar"scope="application"/>),之前使用该新变量。例如,您可以在需要此变量的地方有 几个 JSP文件。所以,你必须醚) 这两个 组的新变量保持上下文路径的 _应用_范围和上网本JSP首先,在其他JSP文件中使用这个变量之前,或b)设置此上下文路径在EVERYJSP文件存储变量,你需要访问它。
<c:set var="foo" value="bar"scope="application"/>
使访问上下文路径更紧凑的更有效方法是设置一个变量,该变量将保存上下文路径并使用 Listener 将其存储在 应用程序范围中。此解决方案与解决方案№3类似,但是好处在于,现在变量保存上下文路径是在Web应用程序 的开头* 设置的 ,并且 在整个应用程序中都可用,不需要其他步骤。 __ *
我们需要一个实现 ServletContextListener 接口的类。这是此类的示例:
package com.example.listener; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; @WebListener public class AppContextListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent event) { ServletContext sc = event.getServletContext(); sc.setAttribute("ctx", sc.getContextPath()); } @Override public void contextDestroyed(ServletContextEvent event) {} }
现在,在JSP中,我们可以使用EL访问此全局变量:
<link type="text/css" rel="stylesheet" href="${ctx}/globalCSS.css" />
注意 @WebListener注释从Servlet 3.0版开始可用。如果使用支持较早Servlet规范的Servlet容器或应用程序服务器,请删除 @WebServlet 批注,而在 部署描述符 (web.xml)中配置侦听器。这是支持最大Servlet版本2.5的容器的 web.xml 文件示例(为简洁起见,省略了其他配置):
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> ... <listener> <listener-class>com.example.listener.AppContextListener</listener-class> </listener> ... </webapp>
根据用户 _@gavenkoa的_建议,您也可以使用如下脚本
<%= request.getContextPath() %>
对于这么小的事情,可能就可以了,只要注意通常不建议在JSP中使用scriptlet。
我个人更喜欢第一种解决方案(大部分时间在我以前的项目中经常使用)或第二种解决方案,因为它们最清晰,直观,明确(IMHO)。但是您选择最适合您的东西。
您可以将Web应用程序部署为 默认应用程序 (即,在 默认的根上下文中 ),因此 无需指定上下文路径 即可访问它。