web-dev-qa-db-ja.com

JSPに外部リソース(CSS / JavaScript / imagesなど)を追加する

外部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>
22
Vishal Anand

404 File Not Foundエラーが発生する理由は、href属性の値として指定されたCSSへのパスにcontext pathがないことです。

HTTPリクエストURLには次の部分が含まれます。

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

request pathは、さらに次の要素で構成されます。

  • Context path:サーブレットのWebアプリケーションの context root とスラッシュ(/)の連結。例:http://Host[:port]/context-root[/url-pattern]

  • Servlet path:このリクエストをアクティブ化したコンポーネントエイリアスに対応するパスセクション。このパスは、スラッシュ(/)で始まります。

  • Path info:コンテキストパスまたはサーブレットパスの一部ではないリクエストパスの一部。

続きを読む こちら


解決策

問題にはいくつかの解決策がありますが、そのいくつかを以下に示します。

1)JSTLから<c:url>タグを使用する

私のJava私が通常使用したWebアプリケーション <c:url> タグfrom [〜#〜] jstl [〜#〜] when CSS/JavaScript/imageおよびその他の静的リソースへのパスを定義することにより、これらのリソースが常にアプリケーションコンテキストに相対的(コンテキストパス)で参照されていることを確認できます。

CSSがWebContentフォルダー内にあると言う場合、これは動作するはずです:

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

動作する理由は、「JavaServer Pages™標準タグライブラリ」バージョン1.2 仕様 7.5(エンファシスマイニング)で説明されています。

7.5 <c:url>
適切な書き換えルールが適用されたURLを構築します。
...
URLは、スキームで始まる絶対URL(例: "http:// server/context/page.jsp")またはJSP.2.2.1のJSP 1.2で定義されている相対URLのいずれかでなければなりませんURL仕様」。結果として、実装はスラッシュで始まるURLにコンテキストパスを追加する(たとえば、「/ page2.jsp」)を使用して、そのようなURLをクライアントブラウザーが適切に解釈できるようにする必要があります。

[〜#〜] note [〜#〜]
JSTLタグ を参照できるようにするために、JSPでTaglibディレクティブを使用することを忘れないでください。 JSPページの例も参照してください here


2)JSP Expression Languageおよび暗黙オブジェクトの使用

代替ソリューションは Expression Language(EL) を使用してアプリケーションコンテキストを追加します。

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

ここで、requestオブジェクトからコンテキストパスを取得しました。そして、リクエストオブジェクトにアクセスするために、pageContextimplicit object を使用しました。


3)JSTLから<c:set>タグを使用する

[〜#〜]免責事項[〜#〜]
このソリューションのアイデアは、 ここ から得られました。

コンテキストパスへのアクセスをソリューション№2よりもコンパクトにするために、まずJSTL <c:set> タグを使用できます。これは 値を設定 EL変数のまたは、後でアクセスするためのJSPスコープ(ページ、リクエスト、セッション、またはアプリケーション)のEL変数のプロパティ。

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

重要事項
デフォルトでは、このような方法で変数を設定するには、このsetタグを含むJSPにアクセスする必要があります少なくとも1回(ケースを含むscope属性を使用してapplicationスコープに値を設定する(<c:set var="foo" value="bar" scope="application" />)、beforeなど、この新しい変数を使用してたとえば、この変数が必要な場所に複数 JSPファイルを作成できます。したがって、a)bothは、他のJSPファイルでこの変数を使用する前に、applicationスコープでコンテキストパスを保持する新しい変数を設定し、このJSPにアクセスする必要があります。 )すべてのJSPファイルにアクセスする必要がある場所で、このコンテキストパス保持変数を設定します。


4)ServletContextListenerの使用

コンテキストパスへのアクセスをよりコンパクトにするためのより効果的な方法は、コンテキストパスを保持する変数を設定し、application 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" />

[〜#〜] note [〜#〜]
@ WebListener アノテーションは、サーブレットバージョン3.0以降で使用できます。古いサーブレット仕様をサポートするサーブレットコンテナまたはアプリケーションサーバーを使用する場合は、@ WebServletアノテーションを削除し、代わりにdeployment descriptor(web。 xml)。最大のサーブレットバージョン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)スクリプトレットを使用する

推奨 ユーザーによる @ gavenkoa として scriptlets を使用することもできます:

<%= request.getContextPath() %>

このような小さなことについては、おそらく大丈夫です。単に 一般にJSPでのスクリプトレットの使用は推奨されていません であることに注意してください。


結論

個人的には、最初のソリューション(以前のプロジェクトでほとんどの場合使用されていた)または2番目のソリューションのどちらかが好まれます。しかし、あなたはあなたに最も合ったものを選びます。


他の考え

Webアプリをdefault application(つまり、デフォルトルートコンテキスト)としてデプロイできるため、コンテキストパスを指定せずににアクセスできます。詳細については、「更新」セクションをお読みください こちら

37
informatik01

次のコードを使用してthisQuestionを解決します... localhostサーバーを使用してファイルを実行する場合、この問題はJspページコードに従って解決します。このコードはjspファイルのHead Tagの間に配置します

<style type="text/css">
    <%@include file="css/style.css" %>
</style>
<script type="text/javascript">
    <%@include file="js/script.js" %>
</script>
2
Parth Patel