Je déploie une webapp sur deux conteneurs différents (Tomcat et Jetty), mais leurs servlets par défaut pour servir le contenu statique ont une manière différente de gérer la structure d'URL que je souhaite utiliser ( détails ).
Je cherche donc à inclure un petit servlet dans la webapp pour servir son propre contenu statique (images, CSS, etc.). Le servlet doit avoir les propriétés suivantes:
- Aucune dépendance externe
- Simple et fiable
- Prise en charge de l'en-
If-Modified-Since
tête (c'est- à -diregetLastModified
méthode personnalisée ) - (Facultatif) Prise en charge de l'encodage gzip, etags, ...
Un tel servlet est-il disponible quelque part? Le plus proche que je puisse trouver est l' exemple 4-10 du livre de servlet.
Mise à jour: La structure d'URL que je souhaite utiliser - au cas où vous vous poseriez la question - est simplement:
<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>
Ainsi, toutes les requêtes doivent être passées au servlet principal, sauf si elles concernent le static
chemin. Le problème est que le servlet par défaut de Tomcat ne prend pas en compte le ServletPath (il recherche donc les fichiers statiques dans le dossier principal), alors que Jetty le fait (il regarde donc dans le static
dossier).
la source
Réponses:
J'ai trouvé une solution légèrement différente. C'est un peu hack-ish, mais voici le mapping:
Ceci mappe simplement tous les fichiers de contenu par extension au servlet par défaut, et tout le reste à "myAppServlet".
Cela fonctionne à la fois dans Jetty et Tomcat.
la source
*.sth
. Si quelqu'un obtient l'URL,example.com/index.jsp?g=.sth
il obtiendra la source du fichier jsp. Ou je me trompe? (Je suis nouveau dans Java EE) J'utilise habituellement un modèle d'url,/css/*
etc.Il n'y a pas besoin d'une implémentation complètement personnalisée du servlet par défaut dans ce cas, vous pouvez utiliser ce simple servlet pour encapsuler la demande dans l'implémentation du conteneur:
la source
J'ai eu de bons résultats avec FileServlet , car il prend en charge à peu près tout HTTP (etags, chunking, etc.).
la source
Modèle abstrait pour un servlet de ressources statiques
En partie basé sur ce blog de 2007, voici un modèle abstrait modernisé et hautement réutilisable pour un servlet qui traite correctement la mise en cache
ETag
,If-None-Match
etIf-Modified-Since
(mais pas de support Gzip et Range; juste pour rester simple; Gzip pourrait être fait avec un filtre ou via configuration du conteneur).Utilisez-le avec l'interface ci-dessous représentant une ressource statique.
Tout ce dont vous avez besoin est juste d'étendre le servlet abstrait donné et d'implémenter la
getStaticResource()
méthode selon le javadoc.Exemple concret servant à partir du système de fichiers:
Voici un exemple concret qui le sert via une URL comme à
/files/foo.ext
partir du système de fichiers du disque local:Exemple concret servant à partir de la base de données:
Voici un exemple concret qui le sert via une URL comme
/files/foo.ext
depuis la base de données via un appel de service EJB qui renvoie votre entité ayant unebyte[] content
propriété:la source
files/%2e%2e/mysecretfile.txt
. Cette demande produitfiles/../mysecretfile.txt
. Je l'ai testé sur Tomcat 7.0.55. Ils appellent cela un répertoire grimpant: owasp.org/index.php/Path_TraversalJ'ai fini par rouler le mien
StaticServlet
. Il prend en charge l'If-Modified-Since
encodage gzip et devrait également pouvoir servir des fichiers statiques à partir de fichiers war. Ce n'est pas du code très difficile, mais ce n'est pas non plus entièrement trivial.Le code est disponible: StaticServlet.java . N'hésitez pas à commenter.
Mise à jour: Khurram pose des questions sur la
ServletUtils
classe référencée dansStaticServlet
. C'est simplement une classe avec des méthodes auxiliaires que j'ai utilisées pour mon projet. La seule méthode dont vous avez besoin estcoalesce
(qui est identique à la fonction SQLCOALESCE
). Voici le code:la source
À en juger par les informations d'exemple ci-dessus, je pense que cet article entier est basé sur un comportement bogué dans Tomcat 6.0.29 et versions antérieures. Voir https://issues.apache.org/bugzilla/show_bug.cgi?id=50026 . La mise à niveau vers Tomcat 6.0.30 et le comportement entre (Tomcat | Jetty) doit fusionner.
la source
svn diff -c1056763 http://svn.apache.org/repos/asf/tomcat/tc6.0.x/trunk/
. Enfin, après avoir marqué ce WONTFIX il y a +3 ans!essaye ça
Edit: Ceci n'est valable que pour la spécification servlet 2.5 et plus.
la source
J'ai eu le même problème et je l'ai résolu en utilisant le code du 'servlet par défaut' de la base de code Tomcat.
https://github.com/apache/tomcat/blob/master/java/org/apache/catalina/servlets/DefaultServlet.java
Le DefaultServlet est le servlet qui sert les ressources statiques (jpg, html, css, gif, etc.) dans Tomcat.
Ce servlet est très efficace et possède certaines des propriétés que vous avez définies ci-dessus.
Je pense que ce code source est un bon moyen de démarrer et de supprimer les fonctionnalités ou les dépendances dont vous n'avez pas besoin.
la source
org.apache.*
. Comment pouvez-vous l'utiliser avec Jetty?J'ai trouvé un excellent tutoriel sur le Web sur une solution de contournement. C'est simple et efficace, je l'ai utilisé dans plusieurs projets avec l'approche des styles d'urls REST:
http://www.kuligowski.pl/java/rest-style-urls-and-url-mapping-for-static-content-apache-tomcat,5
la source
J'ai fait cela en étendant le tomcat DefaultServlet ( src ) et en remplaçant la méthode getRelativePath ().
... Et voici mes mappages de servlet
la source
Pour répondre à toutes les demandes d'une application Spring ainsi que /favicon.ico et les fichiers JSP de / WEB-INF / jsp / * que AbstractUrlBasedView de Spring demandera, vous pouvez simplement remapper le servlet jsp et le servlet par défaut:
Nous ne pouvons pas nous fier au modèle d'url * .jsp sur le mappage standard du servlet jsp car le modèle de chemin '/ *' correspond avant que tout mappage d'extension ne soit vérifié. Le mappage du servlet jsp vers un dossier plus profond signifie qu'il est mis en correspondance en premier. La correspondance avec '/favicon.ico' se produit exactement avant la correspondance du modèle de chemin. Des correspondances de chemin plus profondes fonctionneront, ou des correspondances exactes, mais aucune correspondance d'extension ne peut dépasser la correspondance de chemin '/ *'. Le mappage de «/» au servlet par défaut ne semble pas fonctionner. On pourrait penser que le «/» exact battrait le modèle de chemin «/ *» sur springapp.
La solution de filtrage ci-dessus ne fonctionne pas pour les demandes JSP transférées / incluses de l'application. Pour que cela fonctionne, je devais appliquer le filtre directement à springapp, à quel point la correspondance url-pattern était inutile car toutes les requêtes qui vont à l'application vont également à ses filtres. J'ai donc ajouté une correspondance de modèle au filtre, puis j'ai découvert le servlet 'jsp' et j'ai vu qu'il ne supprimait pas le préfixe de chemin comme le fait le servlet par défaut. Cela a résolu mon problème, qui n'était pas exactement le même mais assez courant.
la source
Vérifié pour Tomcat 8.x: les ressources statiques fonctionnent correctement si le servlet racine est mappé sur "". Pour la servlet 3.x, cela pourrait être fait par
@WebServlet("")
la source
Utilisez org.mortbay.jetty.handler.ContextHandler. Vous n'avez pas besoin de composants supplémentaires tels que StaticServlet.
À la maison jetée,
contextes $ cd
$ cp javadoc.xml static.xml
$ vi static.xml
...
Définissez la valeur de contextPath avec votre préfixe d'URL et définissez la valeur de resourceBase comme chemin de fichier du contenu statique.
Cela a fonctionné pour moi.
la source
Voir StaticFile dans JSOS: http://www.servletsuite.com/servlets/staticfile.htm
la source