Frage

In Java, Web-Anwendungen werden in auf WARs gebündelt. Standardmäßig viele Servlet-Container werden den WAR-Namen als Kontextnamen für die Anwendung verwenden.

So wird myapp.war eingesetzt http://example.com/myapp .

Das Problem ist, dass der Webapp seinen "root" die Auffassung zu sein, nun ja, "root" oder einfach "/", während HTML die Wurzel Ihrer Anwendung in Betracht ziehen würde "/ myapp" sein.

Der Servlet-API und JSP haben Einrichtungen diese zu verwalten. Wenn zum Beispiel in einem Servlet, was Sie tun: response.sendRedirect ( "/ mypage.jsp"), wird der Behälter den Kontext voranstellen und die URL erstellen: http://example.com/myapp/mypage.jsp ".

Sie können jedoch nicht, dass mit, sagen wir, das IMG-Tag in HTML. Wenn Sie das tun Sie werden wahrscheinlich einen 404 bekommen, weil das, was Sie wirklich wollte, war "/myapp/myimage.gif".

Viele Frameworks haben JSP-Tags, die den Kontext als auch bewusst sind, und es gibt verschiedene Möglichkeiten der richtige URLs in JSP (keine besonders elegant) zu machen.

Es ist ein Nitty Problem für Programmierer in einer aus zu springen, wenn eine "App Relative" URL zu verwenden, gegen eine absolute URL.

Schließlich gibt es noch das Problem des Javascript-Code, die URLs on the fly und eingebettete URLs in CSS (für Hintergrundbilder und dergleichen).

erstellen muss

Ich bin gespannt, welche Techniken andere verwenden, um dieses Problem zu mildern und zu arbeiten. Viel einfach Punt und hart Code es, entweder auf Server root oder, was auch immer Kontext sie zu verwenden passieren. Ich weiß schon, dass die Antwort, das ist nicht das, was ich suche.

Was möchten Sie tun?

War es hilfreich?

Lösung

Sie können JSTL verwenden für Urls zu schaffen.

Zum Beispiel <c:url value="/images/header.jpg" /> das Kontextstamm Präfix.

Mit CSS, dies in der Regel kein Problem für mich.

Ich habe eine Web-Root-Struktur wie folgt aus:

/ css
/ Images

In der CSS-Datei, Sie dann müssen nur relative URLs verwenden (../images/header.jpg) und es muss nicht bewusst Kontext root sein.

Wie für JavaScript, was funktioniert für mich einige gemeinsame JavaScript in den Seitenkopf wie folgt mit:

<script type="text/javascript">
var CONTEXT_ROOT = '<%= request.getContextPath() %>';
</script>

Dann können Sie den Kontextstamm in allen Skripten (oder können Sie eine Funktion definieren, Wege zu bauen - ein bisschen flexibler sein kann)

.

Offensichtlich hängt alles von Ihrem mit JSPs und JSTL, aber ich verwende JSF mit Facelets und die beteiligten Techniken sind ähnlich -. Der einzige wirkliche Unterschied ist in einer anderen Art und Weise den Kontext root bekommen

Andere Tipps

Für HTML-Seiten, habe ich nur den HTML-<base>-Tag. Jede relative Verknüpfung (d.h. nicht mit Schema oder / ausgang) wird, um es relativ worden. Es gibt keine saubere Art und Weise sofort von HttpServletRequest zu packen, so brauchen wir etwas Hilfe von JSTL hier.

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<c:set var="req" value="${pageContext.request}" />
<c:set var="url">${req.requestURL}</c:set>
<c:set var="uri">${req.requestURI}</c:set>

<!DOCTYPE html>
<html lang="en">
  <head>
    <base href="${fn:substring(url, 0, fn:length(url) - fn:length(uri))}${req.contextPath}/" />
    <link rel="stylesheet" href="css/default.css">
    <script src="js/default.js"></script>
  </head>
  <body>
    <img src="img/logo.png" />
    <a href="other.jsp">link</a>
  </body>
</html>

Dies hat wiederum jedoch eine Einschränkung: Anker (die #identifier URL) als auch mit dem Basispfad relativ worden. Wenn Sie einen von ihnen haben, möchten Sie es stattdessen auf die Anfrage URL (URI) relativ machen. So ändern sich wie

<a href="#identifier">jump</a>

<a href="${uri}#identifier">jump</a>

In JS, können Sie Zugriff nur das <base> Element aus dem DOM wann immer Sie möchten eine relative URL auf eine absolute URL konvertieren.

var base = document.getElementsByTagName("base")[0].href;

oder wenn Sie jQuery

var base = $("base").attr("href");

In CSS ist das Bild-URLs in Bezug auf die URL des Stylesheets selbst. Also, werfen Sie einfach die Bilder in irgendeinem Ordner relativ zum Stylesheet selbst. Z.

/css/style.css
/css/images/foo.png

und auf sie verweisen wie folgt

background-image: url('images/foo.png');

Wenn Sie eher wie die Bilder in einigen Ordnern auf dem gleichen Niveau wie CSS-Ordner löschen

/css/style.css
/images/foo.png

dann verwenden ../ auf den gemeinsamen übergeordneten Ordner gehen

background-image: url('../images/foo.png');

Siehe auch:

Ich bin mit tardate . Ich habe meine Aufmerksamkeit auf Filter zu bezahlt und haben die Lösung angesichts der Projekt UrlRewriteFilter . Die einfache Konfiguration wie folgt vor:

<rule>
    <from>^.+/resources/(.*)$</from>
    <to>/resources/$1</to>
</rule>

hilft alle Anforderungen für * / Ressourcen Weg weiterleiten zu / Ressourcen übergeben (einschließlich Kontext Pfadpräfix). mit relativen URLs in meinem Design für Hintergrundbilder und andere Fälle So kann ich einfach alle meine setzen Bilder und CSS Dateien unter Ressourcen Ordnern und fortzufahren.

  

Der Servlet-API und JSP   Einrichtungen zu helfen, diese zu verwalten. Zum   Wenn beispielsweise in einem Servlet, Sie tun können:   response.sendRedirect ( "/ mypage.jsp"),   der Behälter wird das Kontext prepend   und erstellen Sie die URL:    http://example.com/myapp/mypage.jsp “.

Ach, vielleicht, vielleicht auch nicht - es hängt von Ihrem Container und der Servlet-Spezifikation!

Servlet 2.3: Neue Funktionen ausgesetzt :

  

Und schließlich, nach einer langen Debatte durch   eine Gruppe von Experten, Servlet API 2.3   und für alle genau hat einmal geklärt   was passiert, auf einem   res.sendRedirect ( "/ index.html") call   für ein Servlet innerhalb einer Ausführung   Nicht-Root-Kontext. Das Problem ist, dass   Servlet API 2.2 erfordert eine unvollständige   Pfad wie „/index.html“ zu sein   durch die Servlet-Container übersetzt   in einen vollständigen Pfad, sagt aber nicht   wie Kontextpfade behandelt werden. wenn die   Servlet Tätigen eines Anrufs ist in ein   Kontext auf dem Pfad „/ ContextPath“   sollte die Umleitung URI übersetzen   relativ zu dem Behälter root   ( http: // server: port / index.html ) oder   Kontextstamm   ( http: // server: port / ContextPath / index.html )?   Für maximale Portabilität, es ist   zwingend notwendig, um das Verhalten zu definieren;   Nach langer Diskussion der Experten   wählte zu übersetzen, bezogen auf die   Behälter Wurzel. Für diejenigen, die wollen,   Kontext relativ, können Sie voranstellen, die   Ausgabe von getContextPath (), um Ihre   URI.

Also nein, mit 2.3 Ihre Wege sind nicht automatisch übersetzt, um den Kontext Pfad enthalten.

ich verwendet habe, Hilfsklassen img-Tags zu erzeugen, usw. Diese Hilfsklasse kümmert sich um prefixing Pfade mit der contextPath der Anwendung. (Dies funktioniert, aber ich weiß nicht wirklich wie es. Wenn jemand eine besseren Alternativen hat, bitte sagen.)

Für Pfade in CSS-Dateien usw. Ich benutze ein Ant-Build-Skript , die eine site.production.css für site.css in der Produktionsumgebung und site.development.css in Entwicklung encironment verwendet.

Als Alternative habe ich manchmal ein Ant-Skript, das ersetzt @token @ Token mit der richtigen Daten für verschiedene environents. In diesem Fall @ ContextPath @ Token würde mit dem richtigen Kontext Pfad ersetzt werden.

Eine Option ist "flach" Anwendungsstruktur und relative URLs, wann immer möglich zu verwenden.

Mit dem „flat“ Ich meine, dass es keine Unterverzeichnisse Anwendungsroot sind, vielleicht nur wenige Verzeichnisse für statische Inhalte wie „images /“. Alle Ihre JSP, Aktion URLs, Servlets gehen direkt unter der Wurzel.

Dies ist nicht vollständig Ihr Problem lösen, sondern vereinfacht es erheblich.

Vilmantas sagte das richtige Wort hier: relative URLs

.

Alles was Sie brauchen in Ihrem IMG zu tun ist, zu verwenden,

<img src="myimage.gif"/>

statt

<img src="/myimage.gif"/>

und es wird auf den App Kontext relativ (wie der Browser die URL um zu gehen interpretiert)

Mit Ausnahme von Sonderfällen, würde ich gegen die Verwendung von absoluten URLs auf diese Weise empfehlen. Je. Absolute URLs sind gut, wenn andere Webapp ist auf etwas in Ihrem Webapp zeigen. Intern - wenn eine Ressource ist in diesem Zusammenhang mit einer zweiten Ressource zeigt -. Die Ressource soll wissen, wo sie lebt, so sollte es einen relativen Pfad zu der zweiten Ressource

ausdrücken kann

Natürlich, werden Sie modulare Komponenten schreiben, die die Ressource nicht wissen, dass sie ist inklusive. Zum Beispiel:

/myapp/user/email.jsp:
Email: <a href="../sendmail.jsp">${user.email}</a>

/myapp/browse/profile.jsp:
<jsp:include page="../user/email.jsp" />

/myapp/home.jsp:
<jsp:include page="../user/email.jsp" />

Also, wie email.jsp kennt den relativen Pfad von sendmail.jsp? Offensichtlich wird der Link auf beiden /myapp/browse/profile.jsp brechen oder es wird auf /myapp/home.jsp brechen. Die Antwort ist, halten Sie alle Ihre URLs in der gleichen Wohnung Filepath Raum. Das heißt, sollte jede URL keine Schrägstriche nach /myapp/ haben.

Dies ist sehr einfach zu erreichen, solange man eine Art von Zuordnung zwischen URLs und den tatsächlichen Dateien, die den Inhalt erzeugen. (Zum Beispiel im Frühjahr, verwenden DispatcherServlet URLs JSP-Dateien oder Ansichten abzubilden.)

Es gibt Sonderfälle. z.B. wenn Sie einen Browser seitige Anwendung in Javascript schreiben, dann wird es schwieriger, einen flachen Filepath Raum aufrechtzuerhalten. In diesem Fall oder in anderen besonderen Fällen, oder einfach nur, wenn Sie eine persönliche Präferenz haben, ist es nicht wirklich eine große Sache <%= request.getContextPath() %> zu verwenden, um einen absoluten Pfad zu erstellen.

Sie können request.getContextPath () verwenden, um absolute URLs zu erstellen, die nicht hart codiert werden zu einem bestimmten Kontext. Wie eine frühere Antwort angegeben, für JavaScript setzen Sie nur eine Variable an der Spitze Ihrer JSP (oder vorzugsweise in einer Vorlage) und Präfix, das als Kontext.

Das funktioniert nicht für CSS-Bildersetzung, wenn Sie eine CSS-Datei dynamisch erzeugen wollen, die andere Probleme verursachen können. Aber da Sie wissen, wo Ihre CSS-Datei in Bezug auf Ihre Bilder ist, können Sie mit relativen URLs wegzukommen.

Aus irgendeinem Grund habe ich Probleme mit IE hatte relative URLs Handhabung und musste mit Ausdrücken mit einem JavaScript-Variable auf den Kontext zurückgreifen. Ich teile nur mein IE Bild Ersatz aus in die eigene Datei und verwendet IE-Makros in die richtigen sind zu ziehen. Es war keine große Sache, weil ich schon, dass ohnehin mit transparenten PNGs zu tun hatte zu tun. Es ist nicht schön, aber es funktioniert.

ich die meisten dieser Techniken verwendet haben (die XSLT-Architektur speichern).

ich glaube, der Kern (und Konsens) des Problems mit potenziell mehreren Verzeichnissen eine Website ist zu müssen.

Wenn Sie Ihre Verzeichnistiefe (in Ermangelung eines besseren Begriffs) konstant ist, dann können Sie sich auf relative URLs in Dinge wie CSS verlassen.

Geist, wird das Layout nicht vollständig flach sein, nur konsequent.

Zum Beispiel haben wir Hierarchien wie / CSS getan, / js / common, / admin, / user. Putting entsprechende Seiten und Ressourcen in den richtigen Verzeichnissen. Mit einer Struktur, wie diese sehr gut mit Container basierte Authentifizierung funktioniert.

Ich habe auch * .css und * .js an dem JSP Servlet abgebildet, und machte sie dynamisch, damit ich sie im Fluge bauen.

Ich habe nur gehofft, es war etwas anderes kann ich übersehen haben.

ich nicht Mittel behaupten, dass die folgenden ein elegantes Problem. In der Tat, im Nachhinein würde ich dieses Problem nicht empfehlen, die (wahrscheinlich) Performance-Einbußen gegeben.

Unsere Web-App JSPs waren streng XML-Rohdaten. Diese Rohdaten wurden dann in ein XSL (serverseitig), die das XHTML die richtigen CSS-Tags und ausspucken angewendet gesendet.

Wir hatten einen einzigen template.xsl, die durch die mehr XSL-Dateien vererbt werden würde, die wir für die verschiedenen Komponenten der Website hatten. Unsere Wege waren alle in einem XSL-Datei mit dem Namen paths.xml definiert:

<?xml version="1.0" encoding="UTF-8"?>
<paths>
    <path name="account" parent="home">Account/</path>
    <path name="css">css/</path>
    <path name="home">servlet/</path>
    <path name="icons" parent="images">icons/</path>
    <path name="images">images/</path>
    <path name="js">js/</path>
</paths>

Ein interner Link würde in XML wie folgt aussehen:

<ilink name="link to icons" type="icons">link to icons</ilink>

Dies würde durch unsere XSL verarbeitet bekommen:

<xsl:template match="ilink">
    <xsl:variable name="temp">
        <xsl:value-of select="$rootpath" />
        <xsl:call-template name="paths">
            <xsl:with-param name="path-name"><xsl:value-of select="@type" /></xsl:with-param>
        </xsl:call-template>
        <xsl:value-of select="@file" />
    </xsl:variable>
        <a href="{$temp}" title="{@name}" ><xsl:value-of select="." /></a>
</xsl:template>

$rootPath wurde auf jede Datei übergeben mit ${applicationScope.contextPath} Die Idee hinter uns mit Hilfe von XML, anstatt nur Hartcodierung es in einer JSP / Java-Datei wurde wollten wir nicht neu kompilieren müssen.

Auch hier ist die Lösung nicht gut auf allen ... aber wir haben es einmal verwenden!

Bearbeiten : Eigentlich ist die Komplexität in unserer Ausgabe entstand, weil wir JSPs nicht in der Lage waren, zu verwenden für unsere gesamte Ansicht. Warum sollte nicht jemand nur ${applicationScope.contextPath} verwenden Sie den Kontextpfad abzurufen? Es war für uns dann in Ordnung.

Wenn Sie eine Website von Grund auf neu erstellen, ich mit @Will Seite -. Ziel für eine konsistente und vorhersagbare URL-Struktur, so dass Sie mit relativen Bezügen kleben

Aber die Dinge können wirklich chaotisch, wenn Sie eine Website aktualisieren, die ursprünglich gebaut wurden direkt unter dem Standort Wurzel „/“ arbeiten (ziemlich häufig für einfache JSP-Sites) auf formal Java EE Verpackung (wo Kontextstamm wird einige Pfade unter der Wurzel sein).

Das eine Menge Code-Änderungen bedeuten kann.

Wenn Sie die Code-Änderungen vermeiden oder verschieben wollen, aber immer noch richtig Kontextstamm Referenzierung zu gewährleisten, ist eine Technik, die ich getestet habe, ist Servlet-Filter zu verwenden. Der Filter kann ohne etwas zu ändern in eine bestehende proejct fallen gelassen werden (außer web.xml) und werden alle URL-Referenzen in der ausgehenden HTML auf den richtigen Pfad neu zuordnen, und auch Umleitungen gewährleisten korrekt verwiesen wird.

Ein Beispiel-Website und verwendbaren Code finden Sie hier: Migration von bestehenden Code-Basis von "/" zu einem nicht-root-Kontext-Pfad

Ich neige dazu, eine Eigenschaft als Teil meines Kerns JavaScript-Bibliothek in meinem schreiben zu können. Ich glaube nicht, es ist perfekt, aber ich denke, es ist das Beste, was ich habe es geschafft, zu erreichen.

Zunächst einmal, ich habe ein Modul, das Teil meiner app Kern ist, die immer verfügbar ist

(function (APP) {
  var ctx;
  APP.setContext = function (val) {
    // protect rogue JS from setting the context.
    if (ctx) {
      return;
    }
    val = val || val.trim();
    // Don't allow a double slash for a context.
    if (val.charAt(0) === '/' && val.charAt(1) === '/') {
      return;
    }
    // Context must both start and end in /.
    if (val.length === 0 || val === '/') {
      val = '/';
    } else {
      if (val.charAt(0) !== '/') {
        val = '/' + val;
      }
      if (val.slice(-1) !== '/') {
        val += '/';
      }
    }
    ctx = val;
  };
  APP.getContext = function () {
    return ctx || '/';
  };
  APP.getUrl = function (val) {
    if (val && val.length > 0) {
      return APP.getContext() + (val.charAt(0) === '/' ? val.substring(1) : val);
    }
    return APP.getContext();
  };
})(window.APP = window.APP || {});

Ich benutze dann Apache Fliesen mit einem gemeinsamen Header, enthält immer die folgenden:

<script type="text/javascript">
  APP.setContext('${pageContext.request['contextPath']}');
  // If preferred use JSTL cor, but it must be available and declared.
  //APP.setContext('<c:url value='/'/>');
</script>

Nun, da ich den Kontext initialisiert habe ich getUrl(path) von überall verwenden kann (js Dateien oder innerhalb jsp / html), die im Rahmen einen absoluten Pfad für das gegebene Eingabestring zurück.

Beachten Sie, dass die folgenden sind beide gleichwertig absichtlich. getUrl wird immer wieder zurückkehren einen absoluten Pfad als ein relativer Pfad, den Sie nicht brauchen den Kontext, in erster Linie zu kennen.

var path = APP.getUrl("/some/path");
var path2 = APP.getUrl("some/path");

Hier ist der beste Weg: Context Umleitung Filter Filter muss vor dem Spiel Erweiterungspunkt angewendet werden und somit Anmerkung @PreMatching verwenden.

Filter der diese Schnittstelle implementieren muss mit @Provider mit Anmerkungen versehen werden, um von der JAX-RS-Laufzeit entdeckt zu werden. Container Anfrage Filterinstanzen können auch dynamisch auf bestimmte Ressource Methoden entdeckt und gebunden werden.

Erklärt mit Beispielcode:

http://writeulearn.com/java-filters/

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top