¿Cómo manejar el contenido estático en Spring MVC?

Estoy desarrollando una aplicación web utilizando Spring MVC 3 y hago que el Servidor DispatcherServlet capture todas las solicitudes a ‘/’ me gusta (web.xml):

   app org.springframework.web.servlet.DispatcherServlet   app /  

Ahora esto funciona como se anuncia, sin embargo, ¿cómo puedo manejar el contenido estático? Previamente, antes de usar URL RESTful, habría capturado todo * .html por ejemplo y enviado eso al DispatcherServlet , pero ahora es un juego de pelota diferente.

Tengo una carpeta / static / que incluye / styles /, / js /, / images / etc y me gustaría excluir / static / * del DispatcherServlet .

Ahora podría obtener recursos estáticos funcionando cuando hice esto:

   app /app/  

Pero quiero que tenga buenas URLs (el punto de que yo use Spring MVC 3) y no la página de destino que es www.domain.com/app/

Tampoco quiero una solución acoplada a tomcat o cualquier otro contenedor de servlets, y debido a que esto es (relativamente) poco tráfico, no necesito un servidor web (como apache httpd) enfrente.

¿Hay una solución limpia para esto?

Como pasé mucho tiempo en este tema, pensé que compartiría mi solución. Desde la spring 3.0.4, hay un parámetro de configuración que se llama (más acerca de eso en el sitio web de la documentación de referencia ) que se puede usar para servir recursos estáticos mientras aún se usa DispatchServlet en la raíz de su sitio.

Para usar esto, use una estructura de directorio que se parezca a la siguiente:

 src/ springmvc/ web/ MyController.java WebContent/ resources/ img/ image.jpg WEB-INF/ jsp/ index.jsp web.xml springmvc-servlet.xml 

El contenido de los archivos debe verse así:

src / springmvc / web / HelloWorldController.java:

 package springmvc.web; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class HelloWorldController { @RequestMapping(value="/") public String index() { return "index"; } } 

WebContent / WEB-INF / web.xml:

 < ?xml version="1.0" encoding="UTF-8"?>   springmvc org.springframework.web.servlet.DispatcherServlet 1   springmvc /   

WebContent / WEB-INF / springmvc-servlet.xml:

 < ?xml version="1.0" encoding="UTF-8"?>                 

WebContent / jsp / index.jsp:

 < %@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 

Page with image

" />

Espero que esto ayude 🙂

Este problema se resuelve en la spring 3.0.4.RELEASE, donde puede usar el elemento de configuración en el archivo de configuración del Spring Expender.

Comprobar la documentación de Spring

En Spring 3.0.x agregue lo siguiente a su servlet-config.xml (el archivo que está configurado en web.xml como contextConfigLocation. También debe agregar el espacio de nombres de mvc, pero solo google para eso si no sabe cómo !;)

Funciona para mi

  

Saludos

Ayub Malik

Si entiendo su problema correctamente, creo que he encontrado una solución a su problema:

Tuve el mismo problema en el que se mostraba la salida sin formato sin estilos css, javascripts ni archivos jquery.

Acabo de agregar asignaciones al servlet “predeterminado”. Lo siguiente fue agregado al archivo web.xml:

   default *.css   default *.js  

Esto debería filtrar las solicitudes de archivos javascript y css del objeto DispatcherRequest.

Nuevamente, no estoy seguro de si esto es lo que buscas, pero funcionó para mí. Creo que “predeterminado” es el nombre del servlet predeterminado dentro de JBoss. No estoy seguro de qué es para otros servidores.

Hay otra publicación de desbordamiento de stack que tiene una excelente solución .

No parece ser específico de Tomcat, es simple y funciona muy bien. He intentado algunas de las soluciones en esta publicación con spring mvc 3.1 pero luego tuve problemas para que mi contenido dynamic se publicara.

En resumen, dice agregar un mapeo de servlet como este:

  default /images/*  

Acabo de lidiar con este problema en Spring MVC 3.0 e inicialmente fui con la opción UrlRewriteFilter. Sin embargo, no estaba contento con esta solución, ya que “no me sentía bien” (no soy el único: consulte el enlace de arriba a los foros de spring donde aparece la palabra “pirateo” varias veces).

Así que se me ocurrió una solución similar a “Desconocido (Google)”, pero pedí prestada la idea de tener todo el contenido estático servido desde / static / (tomado de la versión Spring Roo de la aplicación Pet Store). El servlet “predeterminado” no funcionaba para mí, pero Spring Webflow ResourceServlet sí (también tomado de la aplicación Spring Roo).

Web.xml:

  mainDispatcher org.springframework.web.servlet.DispatcherServlet 2   Resource Servlet org.springframework.js.resource.ResourceServlet 1   mainDispatcher /   Resource Servlet /static/*  

El único cambio que realicé en los JSP fue agregar / static / path a URLs para CSS, JS e imágenes. Por ejemplo, “$ {pageContext.request.contextPath} /static/css/screen.css”.

para los usuarios de Maven, la dependencia de “org.springframework.js.resource.ResourceServlet” es:

  org.springframework.webflow org.springframework.js 2.0.8.RELEASE  

Encontré una forma de evitarlo usando el urlrewritefilter de tuckey. Por favor, siéntete libre de dar una mejor respuesta si tienes una!

En web.xml:

  UrlRewriteFilter org.tuckey.web.filters.urlrewrite.UrlRewriteFilter   UrlRewriteFilter /*   app org.springframework.web.servlet.DispatcherServlet   app /app/*  

En urlrewrite.xml:

   / /app/   ^([^\.]+)$ /app/$1   /app/** /$1  

Esto significa que cualquier uri con un ‘.’ en él (como style.css, por ejemplo) no se volverá a escribir.

Mi propia experiencia con este problema es la siguiente. La mayoría de las páginas web y libros relacionados con Spring parecen sugerir que la syntax más adecuada es la siguiente.

   

La syntax anterior sugiere que puede colocar sus recursos estáticos (CSS, JavaScript, imágenes) en una carpeta llamada “recursos” en la raíz de su aplicación, es decir, / webapp / resources /.

Sin embargo, en mi experiencia (estoy usando Eclipse y el complemento Tomcat), el único enfoque que funciona es si coloca su carpeta de recursos dentro de WEB_INF (o META-INF). Entonces, la syntax que recomiendo es la siguiente.

   

En su JSP (o similar), haga referencia al recurso de la siguiente manera.

  

No hace falta mencionar que toda la pregunta solo surgió porque quería que mi servlet de distribución Spring (controlador frontal) interceptara todo, todo lo dynamic, eso es. Entonces tengo lo siguiente en mi web.xml.

  front-controller  org.springframework.web.servlet.DispatcherServlet  1    front-controller /  

Finalmente, dado que estoy usando las mejores prácticas actuales, tengo lo siguiente en mi controlador frontal servlet xml (ver arriba).

  

Y tengo lo siguiente en la implementación de mi controlador real, para asegurarme de que tengo un método predeterminado para manejar todas las solicitudes entrantes.

 @RequestMapping("/") 

Espero que esto ayude.

Obtuve el mismo problema y encontré la respuesta de Joris muy útil. Pero, además, tengo que agregar

  

al archivo de configuración de servlet. Sin esa asignación de recursos no funcionará y todos los controladores dejarán de funcionar. Espero que esto ayude a alguien.

El URLRewrite es una especie de “hack” si quieres llamarlo así. Lo que se reduce a esto es que estás reinventando la rueda; ya que ya hay soluciones existentes. Otra cosa para recordar es Http Server = contenido estático y servidor de aplicaciones = contenido dynamic (así es como fueron diseñados). Al delegar las responsabilidades adecuadas a cada servidor, maximiza la eficiencia … pero hoy en día esto es probablemente solo una preocupación en entornos de rendimiento crítico y algo así como Tomcat probablemente funcionaría bien en ambos roles la mayor parte del tiempo; pero aún es algo a tener en cuenta, no obstante.

Lo solucioné de esta manera:

  Spring MVC Dispatcher Servlet /   default *.jpg   default *.png   default *.gif   default *.js   default *.css  

Esto funciona en Tomcat y por supuesto Jboss. Sin embargo, al final decidí usar la solución que proporciona Spring (como lo menciona rozky) que es mucho más portátil.

Desde la spring 3, todos los recursos deben asignarse de una manera diferente. Debe usar la etiqueta para especificar la ubicación de los recursos.

Ejemplo:

  

Al hacerlo de esta manera, usted está dirigiendo el servlet del despachador a buscar en los recursos del directorio para buscar el contenido estático.

Mi manera de resolver este problema es colocar todas tus acciones con un prefijo específico como “web” o “servicio” y configurar que todas las url con ese prefijo sean interceptadas por DispatcherServlet.

Solo agrego tres reglas antes de la regla predeterminada de spring (/ **) para urlrewritefilter (urlrewrite.xml) de tuckey para resolver el problema

 < ?xml version="1.0" encoding="utf-8"?> < !DOCTYPE urlrewrite PUBLIC "-//tuckey.org//DTD UrlRewrite 3.0//EN" "http://tuckey.org/res/dtds/urlrewrite3.0.dtd">   / /app/welcome   /scripts/** /scripts/$1   /styles/** /styles/$1   /images/** /images/$1   /** /app/$1   /app/** /$1   

Sé que hay algunas configuraciones para usar los contenidos estáticos, pero mi solución es que simplemente creo una carpeta de aplicaciones web a granel dentro de su tomcat. Esta “aplicación web masiva” solo sirve todos los contenidos estáticos sin aplicaciones de publicación. Esta es una solución sencilla y sin dolor para servir contenido estático a su aplicación de spring real.

Por ejemplo, estoy usando dos carpetas de webapp en mi tomcat.

  1. springapp : se ejecuta solo en aplicaciones web de spring sin contenidos estáticos como imgs, js o css. (dedicado para aplicaciones de spring)
  2. recursos : está sirviendo solo los contenidos estáticos sin JSP, servlet o cualquier tipo de aplicación web java. (dedicado para contenido estático)

Si quiero usar javascript, simplemente agrego el URI para mi archivo javascript.

EX> /resources/path/to/js/myjavascript.js

Para imágenes estáticas, estoy usando el mismo método.

EX> /resources/path/to/img/myimg.jpg

Por último, puse ” restricción de seguridad ” en mi tomcat para bloquear el acceso al directorio real. Puse el rol de usuario “nobody” a la restricción para que la página genere “403 prohibido error” cuando las personas intentaron acceder a la ruta de contenido estático.

Hasta ahora me funciona muy bien. También noté que muchos sitios web populares como Amazon, Twitter y Facebook están usando diferentes URI para servir contenido estático. Para descubrir esto, simplemente haga clic derecho en cualquier contenido estático y verifique su URI.

Usé ambos métodos, que es urlrewrite y anotación, que se basa en mvc 3.0.x de spring y encontré que el enfoque basado en anotaciones es el más adecuado que es

   

En el caso de urlrewrite, tiene que definir lotes de reglas y algún tiempo también obtener la excepción de clase no encontrada para UrlRewriteFilter como ya se proporcionó la dependencia para ello. Descubrí que está sucediendo debido a la presencia de dependencia transitiva, así que de nuevo un paso boostá y tendrá que excluir esa dependencia de pom.xml usando

  tags. 

Así que el enfoque basado en la anotación será el buen negocio.

Esto hizo el trabajo real en mi caso

en web.xml:

 ...  default /images/* /css/* /javascripts/*   spring-mvc-dispatcher /  

Después de encontrar y pasar por el mismo proceso de toma de decisiones descrito aquí, decidí ir con la propuesta de ResourceServlet, que funciona bastante bien.

Tenga en cuenta que obtendrá más información sobre cómo usar webflow en su proceso de creación maven aquí: http://static.springsource.org/spring-webflow/docs/2.0.x/reference/html/ch01s05.html

Si usa el repository central estándar de Maven, el artefacto es (en oposición al paquete fuente referido anteriormente):

  org.springframework.webflow spring-js 2.0.9.RELEASE  

Esto se puede lograr en al menos tres formas.

Soluciones :

  • exponer el html como un archivo de recursos
  • instruir al JspServlet para que también maneje las solicitudes * .html
  • escriba su propio servlet (o pase a otras solicitudes de servlets existentes a * .html).

Para obtener ejemplos completos de código sobre cómo lograr esto, consulte mi respuesta en otra publicación: ¿Cómo asignar solicitudes al archivo HTML en Spring MVC?

El problema es con URLPattern

Cambie su patrón de URL en su mapeo de servlet de “/” a “/ *”

 < ?xml version="1.0" encoding="UTF-8"?>    

y si desea utilizar la configuración basada en anotaciones, use el código siguiente

 @Override public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { configurer.enable(); } 

Para la configuración de spring basada en Java, puede usar lo siguiente

Usando ResourceHandlerRegistry que almacena registros de manejadores de recursos para servir recursos estáticos.

Más información @ WebMvcConfigurerAdapter que define los métodos de callback para personalizar la configuración basada en Java para Spring MVC habilitada a través de @EnableWebMvc.

 @EnableWebMvc @Configurable @ComponentScan("package.to.scan") public class WebConfigurer extends WebMvcConfigurerAdapter { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { registry.addResourceHandler("/static_resource_path/*.jpg").addResourceLocations("server_destination_path"); }