Dodawanie zasobów zewnętrznych (CSS/JavaScript / images itp.) w JSP

Dodałem zewnętrzny arkusz stylów CSS do mojego projektu i umieściłem go w folderze WEB-CONTENTS mojego projektu w Eclipse. Kiedy wdrożyłem go na Tomcat, arkusz stylów nie został zastosowany. Kiedy debugowałem go w Chrome i otworzyłem, dał mi 404 file not found błąd. Dlaczego tak jest i jak to naprawić?

Oto kod:

<%@ 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>
Author: BalusC, 2013-01-27

2 answers

Powodem wystąpienia błędu 404 File Not Found jest brak ścieżki do CSS podanej jako wartość atrybutu href ścieżka kontekstowa.

Adres URL żądania HTTP zawiera następujące części:

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

Ścieżka żądania składa się dodatkowo z następujących elementów:

  • ścieżka kontekstowa : połączenie ukośnika (/) z kontekst korzeń aplikacji webowej servleta. Przykład: http://host[:port]/context-root[/url-pattern]

  • Servlet path: sekcja path odpowiadająca komponentowi alias, który aktywował to żądanie. Ta ścieżka zaczyna się od przodu slash (/).

  • Path info: część ścieżki żądania, która nie jest częścią ścieżka kontekstowa lub ścieżka servleta.

Czytaj więcej tutaj .


Rozwiązania

Istnieje kilka rozwiązań Twojego problemu, oto niektóre z oni:

1) Using <c:url> tag from JSTL

W moich aplikacjach internetowych Java Zwykle używałem <c:url> tag z JSTL przy definiowaniu ścieżki do CSS / JavaScript / image i innych zasobów statycznych. W ten sposób możesz mieć pewność, że do tych zasobów odwołuje się zawsze względem kontekstu aplikacji (ścieżka kontekstowa).

Jeśli mówisz, że Twój CSS znajduje się w katalogu WebContent, to powinno działać:

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

The powód jego działania jest wyjaśniony w " JavaServer Pages ™ Standard Tag Library " version 1.2 specification chapter 7.5 (emfaza mine):

7.5
Buduje adres URL z odpowiednimi regułami przepisywania.
...
Adres URL musi być adresem bezwzględnym począwszy od schematu (np. " http: / / server / context / page.jsp") lub a względny adres URL zdefiniowany w JSP 1.2 w JSP.2.2.1 " względny URL Specyfikacja". Jako konsekwencją, implementacja musi poprzedzać ścieżka kontekstowa do adresu URL zaczynającego się ukośnikiem (np. " / page2.jsp") tak że takie adresy URL mogą być poprawnie interpretowane przez przeglądarkę klienta.

Uwaga
Nie zapomnij użyć dyrektywy Taglib w swoim JSP, aby móc odwoływać się do znaczników JSTL. Zobacz także przykładową stronę JSP tutaj .


2) używanie języka wyrażeń JSP i implicit obiekty

An alternatywnym rozwiązaniem jest użycie języka wyrażeń (EL) do dodania kontekstu aplikacji:

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

Tutaj pobraliśmy ścieżkę kontekstową z obiektu request . Aby uzyskać dostęp do obiektu request użyliśmy pageContext obiekt niejawny.


3) Używanie znacznika <c:set> z JSTL

DISCLAIMER
Idea takiego rozwiązania została zaczerpnięta z tutaj .

Aby dostęp do ścieżki kontekstowej był bardziej zwarty niż w rozwiązaniu №2, możesz najpierw użyć JSTL <c:set> tag, że ustawia wartość zmiennej EL lub właściwość zmiennej EL w dowolnym z zakresów JSP (strona, żądanie, sesja lub aplikacja) dla późniejszego dostępu.

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

WAŻNA UWAGA
Domyślnie, aby ustawić zmienną w taki sposób, JSP zawierający ten znacznik set musi być dostęp do przynajmniej raz (w tym w przypadku ustawienia wartości w aplikacji scope używając atrybutu scope , Jak <c:set var="foo" value="bar" scope="application" />), przed użyciem tej nowej zmiennej. Na przykład, możesz mieć kilka plików JSP, gdzie potrzebujesz tej zmiennej. Więc musisz eter a) zarówno ustawić nową zmienną trzymającą ścieżkę kontekstową waplikacji scope i uzyskać dostęp do tego JSP najpierw, przed użyciem tej zmiennej w innych plikach JSP, lub b) ustawić tę ścieżka kontekstowa trzymająca zmienną w każdym pliku JSP, do którego trzeba uzyskać dostęp.


4) Korzystanie Z ServletContextListener

Bardziej efektywnym sposobem na zwiększenie kompaktowości dostępu do ścieżki kontekstowej jest ustawienie zmiennej, która będzie przechowywać ścieżkę kontekstową i przechowywać ją w aplikacji scope korzystanie z słuchacz. Rozwiązanie to jest podobne do rozwiązania №3, ale zaletą jest to, że teraz ustawiona jest zmienna trzymająca ścieżkę kontekstową tuż przy starcie aplikacji internetowej i jest dostępna w całej aplikacji, nie ma potrzeby wykonywania dodatkowych kroków.

Potrzebujemy klasy, która implementuje ServletContextListener interfejs. Oto przykład takiej klasy:

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) {}

}

Teraz w JSP możemy uzyskać dostęp do tej zmiennej globalnej za pomocą EL:

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

Uwaga
@adnotacja WebListener jest dostępna od wersji Servlet 3.0. Jeśli używasz kontenera servlet lub serwer aplikacji obsługujący starsze specyfikacje serwletów, Usuń adnotację @ WebServlet i zamiast tego skonfiguruj słuchacz w deskryptorze wdrażania (web.xml). Oto przykład web.plik xml dla kontenera, który obsługuje maksymalną wersję Servleta 2.5 (inne konfiguracje są pomijane ze względu na zwięzłość):

<?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) za pomocą skryptów

As suggested by user @gavenkoa możesz również użyć skryptów w następujący sposób:

<%= request.getContextPath() %>

Dla tak małej rzeczy jest chyba OK, tylko zauważ, że ogólnie używanie skryptów w JSP jest odradzane .


Podsumowanie

Osobiście wolę albo pierwsze rozwiązanie (używałem go w moich poprzednich projektach najczęściej), albo drugie, ponieważ są one najbardziej przejrzyste, intuicyjne i jednoznaczne (IMHO). Ale ty wybierasz co Ci odpowiada większość.


Inne myśli

Możesz wdrożyć swoją aplikację internetową jako domyślną aplikację (tj. w domyślnym kontekście głównym ), dzięki czemu można uzyskać do niej dostęp bez podawania ścieżki kontekstowej . Aby uzyskać więcej informacji, przeczytaj sekcję "aktualizacja" tutaj.

 39
Author: informatik01,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-17 19:18:31

Używając poniższego kodu rozwiązujesz to pytanie.... Jeśli uruchomisz plik za pomocą serwera localhost, ten problem rozwiąż, postępując zgodnie z kodem strony JSP.Kod umieszczony pomiędzy znacznikami Head w pliku jsp

<style type="text/css">
    <%@include file="css/style.css" %>
</style>
<script type="text/javascript">
    <%@include file="js/script.js" %>
</script>
 2
Author: Parth Patel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-15 07:18:01