Implemento una aplicación web en dos contenedores diferentes (Tomcat y Jetty), pero sus servlets predeterminados para servir el contenido estático tienen una forma diferente de manejar la estructura de URL que quiero usar ( detalles ).
Por lo tanto, estoy buscando incluir un pequeño servlet en la aplicación web para servir su propio contenido estático (imágenes, CSS, etc.). El servlet debe tener las siguientes propiedades:
- Sin dependencias externas
- Simple y confiable
- Soporte para
If-Modified-Since
encabezado (es decir,getLastModified
método personalizado ) - (Opcional) soporte para codificación gzip, etags, ...
¿Existe un servlet de este tipo en algún lugar? Lo más cercano que puedo encontrar es el ejemplo 4-10 del libro de servlets.
Actualización: la estructura de URL que quiero usar, en caso de que se lo pregunte, es simplemente:
<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>
Por lo tanto, todas las solicitudes deben pasarse al servlet principal, a menos que sean para la static
ruta. El problema es que el servlet predeterminado de Tomcat no tiene en cuenta ServletPath (por lo que busca los archivos estáticos en la carpeta principal), mientras que Jetty sí (por lo que se ve en la static
carpeta).
fuente
Respuestas:
Se me ocurrió una solución ligeramente diferente. Es un poco hack-ish, pero aquí está el mapeo:
Básicamente, esto solo asigna todos los archivos de contenido por extensión al servlet predeterminado y todo lo demás a "myAppServlet".
Funciona tanto en Jetty como en Tomcat.
fuente
*.sth
. Si alguien obtiene la URLexample.com/index.jsp?g=.sth
, obtendrá la fuente del archivo jsp. ¿O estoy equivocado? (Soy nuevo en Java EE) Usualmente uso el patrón de URL/css/*
y etc.No es necesario una implementación completamente personalizada del servlet predeterminado en este caso, puede usar este servlet simple para ajustar la solicitud a la implementación del contenedor:
fuente
He tenido buenos resultados con FileServlet , ya que admite casi todo HTTP (etags, fragmentación, etc.).
fuente
Plantilla abstracta para un servlet de recursos estáticos
En parte basado en este blog de 2007, aquí hay una plantilla abstracta modernizada y altamente reutilizable para un servlet que trata adecuadamente el almacenamiento en caché
ETag
,If-None-Match
yIf-Modified-Since
(pero no admite Gzip y Range; solo para simplificarlo; Gzip podría hacerse con un filtro o vía configuración del contenedor).Úselo junto con la interfaz a continuación que representa un recurso estático.
Todo lo que necesita es simplemente extender desde el servlet abstracto dado e implementar el
getStaticResource()
método de acuerdo con el javadoc.Ejemplo concreto que sirve del sistema de archivos:
Aquí hay un ejemplo concreto que lo sirve a través de una URL como la
/files/foo.ext
del sistema de archivos del disco local:Ejemplo concreto que sirve de la base de datos:
Aquí hay un ejemplo concreto que lo sirve a través de una URL como la
/files/foo.ext
de la base de datos a través de una llamada de servicio EJB que devuelve a su entidad que tiene unabyte[] content
propiedad:fuente
files/%2e%2e/mysecretfile.txt
. Esta solicitud producefiles/../mysecretfile.txt
. Lo probé en Tomcat 7.0.55. Lo llaman un directorio de escalada: owasp.org/index.php/Path_TraversalTerminé rodando la mía
StaticServlet
. Es compatibleIf-Modified-Since
codificación gzip y también debería ser capaz de servir archivos estáticos de archivos de guerra. No es un código muy difícil, pero tampoco es del todo trivial.El código está disponible: StaticServlet.java . Siéntase libre de comentar.
Actualización: Khurram pregunta sobre la
ServletUtils
clase a la que se hace referenciaStaticServlet
. Es simplemente una clase con métodos auxiliares que utilicé para mi proyecto. El único método que necesita escoalesce
(que es idéntico a la función SQLCOALESCE
). Este es el código:fuente
A juzgar por la información de ejemplo anterior, creo que todo este artículo se basa en un comportamiento con errores en Tomcat 6.0.29 y anteriores. Ver https://issues.apache.org/bugzilla/show_bug.cgi?id=50026 . Actualice a Tomcat 6.0.30 y el comportamiento entre (Tomcat | Jetty) debería fusionarse.
fuente
svn diff -c1056763 http://svn.apache.org/repos/asf/tomcat/tc6.0.x/trunk/
. ¡Por fin, después de marcar este WONTFIX hace +3 años!prueba esto
Editar: esto solo es válido para la especificación del servlet 2.5 en adelante.
fuente
Tuve el mismo problema y lo resolví usando el código del 'servlet predeterminado' de la base de código de Tomcat.
https://github.com/apache/tomcat/blob/master/java/org/apache/catalina/servlets/DefaultServlet.java
El DefaultServlet es el servlet que sirve a los recursos estáticos (jpg, html, css, gif, etc.) en Tomcat.
Este servlet es muy eficiente y tiene algunas de las propiedades que definió anteriormente.
Creo que este código fuente es una buena manera de iniciar y eliminar la funcionalidad o las dependencias que no necesita.
fuente
org.apache.*
. ¿Cómo puedes usarlo con Jetty?Encontré un gran tutorial en la web sobre algunas soluciones. Es simple y eficiente, lo usé en varios proyectos con el enfoque de estilos de URL REST:
http://www.kuligowski.pl/java/rest-style-urls-and-url-mapping-for-static-content-apache-tomcat,5
fuente
Hice esto extendiendo el Tomcat DefaultServlet ( src ) y anulando el método getRelativePath ().
... Y aquí están mis asignaciones de servlet
fuente
Para atender todas las solicitudes de una aplicación Spring, así como /favicon.ico y los archivos JSP de / WEB-INF / jsp / * que solicitará AbstractUrlBasedView de Spring, puede reasignar el servlet jsp y el servlet predeterminado:
No podemos confiar en el patrón de url * .jsp en la asignación estándar para el servlet jsp porque el patrón de ruta '/ *' coincide antes de que se verifique cualquier asignación de extensión. La asignación del servlet jsp a una carpeta más profunda significa que coincide primero. La coincidencia '/favicon.ico' ocurre exactamente antes de la coincidencia del patrón de ruta. Las coincidencias de ruta más profundas funcionarán, o coincidencias exactas, pero ninguna coincidencia de extensión puede superar la coincidencia de ruta '/ *'. La asignación '/' al servlet predeterminado no parece funcionar. Se podría pensar que el '/' exacto superaría el patrón de ruta '/ *' en springapp.
La solución de filtro anterior no funciona para las solicitudes JSP reenviadas / incluidas de la aplicación. Para que funcione, tuve que aplicar el filtro a springapp directamente, en ese momento la coincidencia del patrón de url fue inútil ya que todas las solicitudes que van a la aplicación también van a sus filtros. Entonces agregué la coincidencia de patrones al filtro y luego aprendí sobre el servlet 'jsp' y vi que no elimina el prefijo de ruta como lo hace el servlet predeterminado. Eso resolvió mi problema, que no era exactamente el mismo, sino bastante común.
fuente
Comprobado para Tomcat 8.x: los recursos estáticos funcionan bien si el servlet raíz se asigna a "". Para el servlet 3.x se podría hacer por
@WebServlet("")
fuente
Use org.mortbay.jetty.handler.ContextHandler. No necesita componentes adicionales como StaticServlet.
En la casa del embarcadero,
contextos $ cd
$ cp javadoc.xml static.xml
$ vi static.xml
...
Establezca el valor de contextPath con su prefijo de URL y establezca el valor de resourceBase como la ruta del archivo del contenido estático.
Funcionó para mi.
fuente
Ver StaticFile en JSOS: http://www.servletsuite.com/servlets/staticfile.htm
fuente