Ich stelle eine Webanwendung auf zwei verschiedenen Containern bereit (Tomcat und Jetty), aber ihre Standardservlets zum Bereitstellen des statischen Inhalts haben eine andere Art, mit der URL-Struktur umzugehen, die ich verwenden möchte ( Details ).
Ich möchte daher ein kleines Servlet in die Webanwendung aufnehmen, um seinen eigenen statischen Inhalt (Bilder, CSS usw.) bereitzustellen. Das Servlet sollte die folgenden Eigenschaften haben:
- Keine externen Abhängigkeiten
- Einfach und zuverlässig
- Unterstützung für
If-Modified-Since
Header (dh benutzerdefiniertegetLastModified
Methode) - (Optional) Unterstützung für GZIP-Codierung, Etags, ...
Ist ein solches Servlet irgendwo verfügbar? Das nächste, das ich finden kann, ist Beispiel 4-10 aus dem Servlet-Buch.
Update: Die URL-Struktur, die ich verwenden möchte - falls Sie sich fragen - ist einfach:
<servlet-mapping>
<servlet-name>main</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/static/*</url-pattern>
</servlet-mapping>
Daher sollten alle Anforderungen an das Hauptservlet übergeben werden, es sei denn, sie beziehen sich auf den static
Pfad. Das Problem ist, dass das Standardservlet von Tomcat den ServletPath nicht berücksichtigt (also sucht es nach den statischen Dateien im Hauptordner), während Jetty dies tut (also sucht es im static
Ordner).
quelle
Antworten:
Ich habe eine etwas andere Lösung gefunden. Es ist ein bisschen hackig, aber hier ist das Mapping:
Dies ordnet im Grunde nur alle Inhaltsdateien nach Erweiterung dem Standardservlet und alles andere "myAppServlet" zu.
Es funktioniert sowohl in Jetty als auch in Tomcat.
quelle
*.sth
. Wenn jemand eine URLexample.com/index.jsp?g=.sth
erhält, erhält er die Quelle der JSP-Datei. Oder irre ich mich? (Ich bin neu in Java EE) Ich benutze normalerweise URL-Muster/css/*
und etc.In diesem Fall ist keine vollständig benutzerdefinierte Implementierung des Standardservlets erforderlich. Mit diesem einfachen Servlet können Sie die Anforderung in die Implementierung des Containers einschließen:
quelle
Ich habe mit FileServlet gute Ergebnisse erzielt , da es fast das gesamte HTTP (Etags, Chunking usw.) unterstützt.
quelle
Abstrakte Vorlage für ein statisches Ressourcenservlet
Teilweise basierend auf diesem Blog aus dem Jahr 2007, ist hier eine modernisierte und in hohem Maße wiederverwendbare abstrakte Vorlage für ein Servlet, das sich ordnungsgemäß mit Caching befasst
ETag
,If-None-Match
undIf-Modified-Since
(aber keine Unterstützung für Gzip und Range; nur um es einfach zu halten; Gzip könnte mit einem Filter oder via durchgeführt werden Containerkonfiguration).Verwenden Sie es zusammen mit der folgenden Schnittstelle, die eine statische Ressource darstellt.
Sie müssen lediglich das angegebene abstrakte Servlet erweitern und die
getStaticResource()
Methode gemäß Javadoc implementieren .Konkretes Beispiel für das Dateisystem:
Hier ist ein konkretes Beispiel, das es über eine URL wie
/files/foo.ext
aus dem lokalen Datenträger-Dateisystem bereitstellt:Konkretes Beispiel aus der Datenbank:
Hier ist ein konkretes Beispiel, das es über eine URL wie
/files/foo.ext
aus der Datenbank über einen EJB-Serviceaufruf bereitstellt, der Ihre Entität mit einerbyte[] content
Eigenschaft zurückgibt :quelle
files/%2e%2e/mysecretfile.txt
. Diese Anfrage erzeugtfiles/../mysecretfile.txt
. Ich habe es auf Tomcat 7.0.55 getestet. Sie nennen es ein Kletterverzeichnis: owasp.org/index.php/Path_TraversalAm Ende rollte ich meine eigenen
StaticServlet
. Es unterstützt dieIf-Modified-Since
GZIP-Codierung und sollte auch statische Dateien aus War-Dateien bereitstellen können. Es ist kein sehr schwieriger Code, aber auch nicht ganz trivial.Der Code ist verfügbar: StaticServlet.java . Fühlen Sie sich frei zu kommentieren.
Update: Khurram fragt nach der
ServletUtils
Klasse, auf die verwiesen wirdStaticServlet
. Es ist einfach eine Klasse mit Hilfsmethoden, die ich für mein Projekt verwendet habe. Die einzige Methode, die Sie benötigen, istcoalesce
(die mit der SQL-Funktion identisch istCOALESCE
). Dies ist der Code:quelle
Nach den obigen Beispielinformationen zu urteilen, basiert dieser gesamte Artikel auf einem fehlerhaften Verhalten in Tomcat 6.0.29 und früheren Versionen. Siehe https://issues.apache.org/bugzilla/show_bug.cgi?id=50026 . Aktualisieren Sie auf Tomcat 6.0.30 und das Verhalten zwischen (Tomcat | Jetty) sollte zusammengeführt werden.
quelle
svn diff -c1056763 http://svn.apache.org/repos/asf/tomcat/tc6.0.x/trunk/
. Endlich, nachdem ich dieses WONTFIX vor +3 Jahren markiert habe!Versuche dies
Bearbeiten: Dies gilt nur für die Servlet 2.5-Spezifikation und höher.
quelle
Ich hatte das gleiche Problem und löste es mit dem Code des 'Standard-Servlets' aus der Tomcat-Codebasis.
https://github.com/apache/tomcat/blob/master/java/org/apache/catalina/servlets/DefaultServlet.java
Das DefaultServlet ist das Servlet, das die statischen Ressourcen (JPG, HTML, CSS, GIF usw.) in Tomcat bereitstellt.
Dieses Servlet ist sehr effizient und hat einige der oben definierten Eigenschaften.
Ich denke, dass dieser Quellcode ein guter Weg ist, um die Funktionen oder Abhängigkeiten zu starten und zu entfernen, die Sie nicht benötigen.
quelle
org.apache.*
. Wie können Sie es mit Jetty verwenden?Ich habe im Web ein großartiges Tutorial über eine Problemumgehung gefunden. Es ist einfach und effizient. Ich habe es in mehreren Projekten mit REST-URLs verwendet.
http://www.kuligowski.pl/java/rest-style-urls-and-url-mapping-for-static-content-apache-tomcat,5
quelle
Dazu habe ich das tomcat DefaultServlet ( src ) erweitert und die Methode getRelativePath ( ) überschrieben.
... und hier sind meine Servlet-Zuordnungen
quelle
Um alle Anforderungen einer Spring-App sowie von /favicon.ico und den JSP-Dateien von / WEB-INF / jsp / * zu bearbeiten, die Spring in AbstractUrlBasedView anfordert, können Sie einfach das jsp-Servlet und das Standardservlet neu zuordnen:
Wir können uns bei der Standardzuordnung für das jsp-Servlet nicht auf das URL-Muster * .jsp verlassen, da das Pfadmuster '/ *' übereinstimmt, bevor eine Erweiterungszuordnung überprüft wird. Wenn Sie das JSP-Servlet einem tieferen Ordner zuordnen, wird es zuerst abgeglichen. Der Abgleich von '/favicon.ico' erfolgt genau vor dem Abgleich des Pfadmusters. Tiefere Pfadübereinstimmungen funktionieren oder genaue Übereinstimmungen, aber keine Erweiterungsübereinstimmungen können über die Pfadübereinstimmung '/ *' hinausgehen. Die Zuordnung von '/' zum Standardservlet scheint nicht zu funktionieren. Sie würden denken, das genaue '/' würde das '/ *' - Pfadmuster auf springapp übertreffen.
Die obige Filterlösung funktioniert nicht für weitergeleitete / eingeschlossene JSP-Anforderungen aus der Anwendung. Damit es funktioniert, musste ich den Filter direkt auf springapp anwenden. Zu diesem Zeitpunkt war der URL-Mustervergleich nutzlos, da alle Anforderungen, die an die Anwendung gehen, auch an deren Filter gehen. Also habe ich dem Filter einen Mustervergleich hinzugefügt und dann etwas über das 'jsp'-Servlet erfahren und festgestellt, dass das Pfadpräfix nicht wie beim Standard-Servlet entfernt wird. Das löste mein Problem, das nicht genau das gleiche war, aber häufig genug.
quelle
Auf Tomcat 8.x geprüft: Statische Ressourcen funktionieren einwandfrei, wenn das Root-Servlet "" zugeordnet ist. Für Servlet 3.x könnte es von gemacht werden
@WebServlet("")
quelle
Verwenden Sie org.mortbay.jetty.handler.ContextHandler. Sie benötigen keine zusätzlichen Komponenten wie StaticServlet.
Am Steghaus,
$ cd Kontexte
$ cp javadoc.xml static.xml
$ vi static.xml
...
Legen Sie den Wert von contextPath mit Ihrem URL-Präfix fest und legen Sie den Wert von resourceBase als Dateipfad des statischen Inhalts fest.
Es hat bei mir funktioniert.
quelle
Siehe StaticFile in JSOS: http://www.servletsuite.com/servlets/staticfile.htm
quelle