我向项目添加了外部CSS样式表,并将其放置在Eclipse中项目的WEB-CONTENTS文件夹中。当我在Tomcat上部署它时,没有应用样式表。当我在Chrome中调试并打开它时,出现了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路径缺少上下文路径。
HTTP请求URL包含以下部分:
http://[host]:[port][request-path]?[query-string]
请求路径进一步由以下元素组成:
上下文路径:正斜杠(/)与Servlet Web应用程序的context root的串联。示例:
http://host[:port]/context-root[/url-pattern]
Servlet路径:与组件相对应的路径部分
激活此请求的别名。这条路始于前进
斜杠(/)。
路径信息:请求路径的一部分,不属于
上下文路径或servlet路径。
阅读更多here。
解决方案
有几种解决您的问题的方法,以下是其中一些:
1)使用JSTL中的
<c:url>
标记在我的Java Web应用程序中,当定义CSS / JavaScript / image和其他静态资源的路径时,通常使用
<c:url>
中的JSTL标记。这样,您可以确保始终相对于应用程序上下文(上下文路径)引用这些资源。如果您说您的CSS位于WebContent文件夹中,那么这应该可以工作:
<link type="text/css" rel="stylesheet" href="<c:url value="/globalCSS.css" />" />
它起作用的原因在“ JavaServer Pages™标准标记库”版本1.2 specification 7.5章中进行了说明(重点是我的):
7.5
使用适当的重写规则构建URL。
...
该URL必须是绝对URL
以方案开头(例如“ http:// server / context / page.jsp”)或
相对URL,如JSP.2.2.1“相对URL中的JSP 1.2所定义
规范”。因此,实施必须先于
以斜杠开头的网址的上下文路径(例如“ /page2.jsp”),因此
客户端浏览器可以正确解释此类URL。
注意
不要忘记在JSP中使用Taglib指令来引用JSTL tags。另请参见示例JSP页面here。
2)使用JSP表达式语言和隐式对象
另一种解决方案是使用Expression Language (EL)添加应用程序上下文:
<link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath}/globalCSS.css" />
在这里,我们从请求对象中检索了上下文路径。为了访问请求对象,我们使用了pageContext implicit object。
3)使用JSTL中的
<c:set>
标记免责声明
此解决方案的想法来自here。
为了使访问上下文路径比解决方案№2更紧凑,您可以首先使用JSTL
<c:set>
标记,该标记是EL变量的sets the value或任何JSP范围(页面,请求,会话或应用程序)以供以后访问。<c:set var="root" value="${pageContext.request.contextPath}"/>
...
<link type="text/css" rel="stylesheet" href="${root}/globalCSS.css" />
重要的提示
默认情况下,为了以这种方式设置变量,在使用之前,必须至少访问一次包含此set标签的JSP(包括在使用scope属性(例如
<c:set var="foo" value="bar" scope="application" />
在应用程序范围中设置值的情况下))。这个新变量。例如,您可以在需要此变量的地方有几个JSP文件。因此,您必须以太a)都在应用程序范围内设置新的变量上下文上下文路径并先访问此JSP,然后再在其他JSP文件中使用此变量,或b)在需要的每个JSP文件中设置此上下文路径变量。访问它。4)使用ServletContextListener
使访问上下文路径更紧凑的更有效方法是设置一个变量,该变量将保存上下文路径并使用scope将其存储在应用程序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" />
注意
从Servlet 3.0版开始,@WebListener注释可用。如果使用支持较早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>
5)使用脚本
作为用户suggested的@gavenkoa,您还可以这样使用scriptlets:
<%= request.getContextPath() %>
对于这么小的事情,可能没问题,只需注意generally the use of scriptlets in JSP is discouraged。
结论
我个人更喜欢第一种解决方案(大部分时间在我以前的项目中经常使用)或第二种解决方案,因为它们最清晰,直观,明确(IMHO)。但是您选择最适合您的东西。
其他想法
您可以将网络应用部署为默认应用(即在默认的根上下文中),因此无需指定上下文路径即可对其进行访问。有关更多信息,请阅读“更新”部分here。
关于jsp - 在JSP中添加外部资源(CSS/JavaScript/图像等),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51748145/