在 JSP 中添加外部资源(CSS/JavaScript/图像等) [英] Adding external resources (CSS/JavaScript/images etc) in JSP

查看:38
本文介绍了在 JSP 中添加外部资源(CSS/JavaScript/图像等)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的项目中添加了一个外部 CSS 样式表,并放置在 Eclipse 中我的项目的 WEB-CONTENTS 文件夹中.当我在 Tomcat 上部署它时,没有应用样式表.当我在 Chrome 中调试它并打开它时,它给了我 404 file not found 错误.为什么会这样以及如何解决?

I added an external CSS stylesheet to my project and placed in the WEB-CONTENTS folder of my project in Eclipse. When I deployed it on the Tomcat, the stylesheet was not applied. When I debugged it in Chrome and opened it, it gave me 404 file not found error. Why is that and how to fix it?

代码如下:

<%@ 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 错误的原因是您的 CSS 路径作为 href 属性缺失上下文路径.

The reason that you get the 404 File Not Found error, is that your path to CSS given as a value to the href attribute is missing context path.

一个 HTTP 请求 URL 包含以下部分:

An HTTP request URL contains the following parts:

http://[host]:[port][request-path]?[query-string]

请求路径进一步由以下元素组成:

The request path is further composed of the following elements:

  • Context path: A concatenation of a forward slash (/) with the context root of the servlet's web application. Example: http://host[:port]/context-root[/url-pattern]

Servlet path:组件对应的路径部分激活此请求的别名.这条路从前进开始斜线 (/).

Servlet path: The path section that corresponds to the component alias that activated this request. This path starts with a forward slash (/).

Path info:请求路径中不属于上下文路径或 servlet 路径.

Path info: The part of the request path that is not part of the context path or the servlet path.

此处阅读更多信息.

您的问题有多种解决方案,以下是其中一些:

There are several solutions to your problem, here are some of them:

在我的 Java Web 应用程序中,我通常使用 定义 CSS 路径时来自 JSTL 标记/JavaScript/image 和其他静态资源.通过这样做,您可以确保引用这些资源总是相对于应用程序上下文(上下文路径).

In my Java web applications I usually used <c:url> tag from JSTL when defining the path to CSS/JavaScript/image and other static resources. By doing so you can be sure that those resources are referenced always relative to the application context (context path).

如果您说您的 CSS 位于 WebContent 文件夹内,那么这应该可以:

If you say, that your CSS is located inside WebContent folder, then this should work:

<link type="text/css" rel="stylesheet" href="<c:url value="/globalCSS.css" />" />

JavaServer Pages™ 标准标记库"版本 1.2 规范第 7.5 章(强调我的):

The reason why it works is explained in the "JavaServer Pages™ Standard Tag Library" version 1.2 specification chapter 7.5 (emphasis mine):

7.5
构建一个应用了正确重写规则的 URL.
...
URL 必须是绝对 URL以方案开头(例如http://server/context/page.jsp")或JSP.2.2.1 中 JSP 1.2 定义的相对 URL 相对 URL规范".因此,实现必须在前面加上以斜杠开头的 URL 的上下文路径(例如/page2.jsp")所以客户端浏览器可以正确解释此类 URL.

7.5 <c:url>
Builds a URL with the proper rewriting rules applied.
...
The URL must be either an absolute URL starting with a scheme (e.g. "http:// server/context/page.jsp") or a relative URL as defined by JSP 1.2 in JSP.2.2.1 "Relative URL Specification". As a consequence, an implementation must prepend the context path to a URL that starts with a slash (e.g. "/page2.jsp") so that such URLs can be properly interpreted by a client browser.

注意
不要忘记在 JSP 中使用 Taglib 指令,以便能够引用 JSTL 标签.另请参阅此处的示例 JSP 页面.

NOTE
Don't forget to use Taglib directive in your JSP to be able to reference JSTL tags. Also see an example JSP page here.


一个替代解决方案是使用表达语言 (EL) 添加应用程序上下文:

An alternative solution is using Expression Language (EL) to add application context:

<link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath}/globalCSS.css" />

这里我们从 request 对象中检索了上下文路径.为了访问请求对象,我们使用了 pageContext 隐式对象.

Here we have retrieved the context path from the request object. And to access the request object we have used the pageContext implicit object.


免责声明
这个解决方案的想法来自 这里.

为了使访问上下文路径比解决方案№2更紧凑,您可以首先使用JSTL 标签,即 设置 EL 变量的值或任何 JSP 范围(页面、请求、会话或应用程序)供以后访问.

To make accessing the context path more compact than in the solution №2, you can first use the JSTL <c:set> tag, that sets the value of an EL variable or the property of an EL variable in any of the JSP scopes (page, request, session, or application) for later access.

<c:set var="root" value="${pageContext.request.contextPath}"/>
...
<link type="text/css" rel="stylesheet" href="${root}/globalCSS.css" />

重要提示
默认情况下,为了以这种方式设置变量,必须至少访问一次包含此 set 标记的 JSP(包括在application 范围使用 scope 属性,例如 <c:set var="foo" value="bar" scope="application"/>),之前 使用这个新变量.例如,您可以在需要此变量的地方有几个 JSP 文件.因此,您必须 a) 两者application 范围内设置保存上下文路径的新变量,并在其他 JSP 文件中使用此变量之前首先访问此 JSP,或 b)在您需要访问的每个 JSP 文件中设置此上下文路径保存变量.

IMPORTANT NOTE
By default, in order to set the variable in such manner, the JSP that contains this set tag must be accessed at least once (including in case of setting the value in the application scope using scope attribute, like <c:set var="foo" value="bar" scope="application" />), before using this new variable. For instance, you can have several JSP files where you need this variable. So you must ether a) both set the new variable holding context path in the application scope AND access this JSP first, before using this variable in other JSP files, or b) set this context path holding variable in EVERY JSP file, where you need to access to it.


使访问上下文路径更紧凑的更有效方法是设置一个变量来保存上下文路径并将其存储在应用程序中范围 使用 听众.此解决方案与解决方案 №3 类似,但好处是现在变量保存上下文路径设置就在 Web 应用程序的开头,并且在应用程序范围内可用,无需额外的步骤.

The more effective way to make accessing the context path more compact is to set a variable that will hold the context path and store it in the application scope using a Listener. This solution is similar to solution №3, but the benefit is that now the variable holding context path is set right at the start of the web application and is available application wide, no need for additional steps.

我们需要一个实现 ServletContextListener 界面.这是此类的示例:

We need a class that implements ServletContextListener interface. Here is an example of such class:

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 访问这个全局变量:

Now in a JSP we can access this global variable using 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 文件示例(为简洁起见,省略了其他配置):

NOTE
@WebListener annotation is available since Servlet version 3.0. If you use a servlet container or application server that supports older Servlet specifications, remove the @WebServlet annotation and instead configure the listener in the deployment descriptor (web.xml). Here is an example of web.xml file for the container that supports maximum Servlet version 2.5 (other configurations are omitted for the sake of brevity):

<?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 您也可以使用 scriptlets 像这样:

<%= request.getContextPath() %>

对于这么小的事情它可能没问题,只需注意通常不鼓励在 JSP 中使用 scriptlet.

For such a small thing it is probably OK, just note that generally the use of scriptlets in JSP is discouraged.


我个人更喜欢第一个解决方案(大部分时间在我以前的项目中使用它)或第二个,因为它们最清晰、直观和明确(恕我直言).但你会选择最适合你的.

I personally prefer either the first solution (used it in my previous projects most of the time) or the second, as they are most clear, intuitive and unambiguous (IMHO). But you choose whatever suits you most.

您可以将您的网络应用程序部署为默认应用程序(即在默认根上下文中),这样就可以在不指定上下文路径的情况下访问它强>.有关详细信息,请阅读此处的更新"部分.

You can deploy your web app as the default application (i.e. in the default root context), so it can be accessed without specifying context path. For more info read the "Update" section here.

这篇关于在 JSP 中添加外部资源(CSS/JavaScript/图像等)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆