tutorial mvc example español spring-mvc

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



spring mvc tutorial español pdf (22)

A partir de Spring 3, todos los recursos deben mapearse de una manera diferente. Debe usar la etiqueta para especificar la ubicación de los recursos.

Ejemplo:

<mvc:resources mapping="/resources/**" location="/resources/" />

Al hacer esto, usted está dirigiendo al servlet del despachador para que busque en los recursos del directorio para buscar el contenido estático.

Estoy desarrollando una aplicación web utilizando Spring MVC 3 y tengo el DispatcherServlet capturando todas las solicitudes a ''/'' como así (web.xml):

<servlet> <servlet-name>app</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>app</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>

Ahora esto funciona como se anuncia, sin embargo, ¿cómo puedo manejar el contenido estático? Anteriormente, antes de usar las URL RESTful, pude haber capturado todos los * .html por ejemplo y haberlos enviado 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 trabajando cuando hice esto:

<servlet-mapping> <servlet-name>app</servlet-name> <url-pattern>/app/</url-pattern> </servlet-mapping>

Pero quiero que tenga buenas URL (el punto de mi uso de Spring MVC 3) no la página de destino en www.domain.com/app/

Tampoco quiero una solución acoplada a Tomcat ni a ningún otro contenedor de servlets, y debido a que este es un tráfico (relativamente) bajo, no necesito un servidor web (como Apache httpd) enfrente.

¿Hay una solución limpia para esto?


Acabo de agregar tres reglas antes de la regla predeterminada de primavera (/ **) al urlrewritefilter de tuckey (urlrewrite.xml) 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"> <urlrewrite default-match-type="wildcard"> <rule> <from>/</from> <to>/app/welcome</to> </rule> <rule> <from>/scripts/**</from> <to>/scripts/$1</to> </rule> <rule> <from>/styles/**</from> <to>/styles/$1</to> </rule> <rule> <from>/images/**</from> <to>/images/$1</to> </rule> <rule> <from>/**</from> <to>/app/$1</to> </rule> <outbound-rule> <from>/app/**</from> <to>/$1</to> </outbound-rule> </urlrewrite>


Acabo de lidiar con este problema en Spring MVC 3.0 e inicialmente opté por la opción UrlRewriteFilter. Sin embargo, no estaba contento con esta solución, ya que "no se sentía bien" (no soy el único, vea el enlace anterior a los foros de primavera donde aparece la palabra "piratear" varias veces).

Así que se me ocurrió una solución similar a la de "Desconocido (Google)" anterior, pero tomé 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 funcionó para mí, pero el Spring Webflow ResourceServlet sí lo hizo (también tomado de la aplicación generada Spring Roo).

Web.xml:

<servlet> <servlet-name>mainDispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet> <servlet-name>Resource Servlet</servlet-name> <servlet-class>org.springframework.js.resource.ResourceServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>mainDispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>Resource Servlet</servlet-name> <url-pattern>/static/*</url-pattern> </servlet-mapping>

El único cambio que hice en JSP fue agregar la ruta / static / a las URL para CSS, JS e imágenes. Por ejemplo, "$ {pageContext.request.contextPath} /static/css/screen.css".

para usuarios de Maven, la dependencia para "org.springframework.js.resource.ResourceServlet" es:

<dependency> <groupId>org.springframework.webflow</groupId> <artifactId>org.springframework.js</artifactId> <version>2.0.8.RELEASE</version> </dependency>


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

Para usar esto, use una estructura de directorios que se parece a lo 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 como:

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"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>springmvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>

Contenido web / WEB-INF / springmvc-servlet.xml:

<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <!-- not strictly necessary for this example, but still useful, see http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/mvc.html#mvc-ann-controller for more information --> <context:component-scan base-package="springmvc.web" /> <!-- the mvc resources tag does the magic --> <mvc:resources mapping="/resources/**" location="/resources/" /> <!-- also add the following beans to get rid of some exceptions --> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" /> <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping"> </bean> <!-- JSTL resolver --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> <property name="prefix" value="/WEB-INF/jsp/" /> <property name="suffix" value=".jsp" /> </bean> </beans>

Contenido Web / jsp / index.jsp:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <h1>Page with image</h1> <!-- use c:url to get the correct absolute path --> <img src="<c:url value="/resources/img/image.jpg" />" />

Espero que esto ayude :-)


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

Tenga en cuenta que puede obtener más información sobre cómo utilizar el flujo web en su proceso de construcción de maven aquí: http://static.springsource.org/spring-webflow/docs/2.0.x/reference/html/ch01s05.html

Si utiliza el repositorio central estándar de Maven, el artefacto es (en oposición al paquete de fuentes de resortes antes mencionado):

<dependency> <groupId>org.springframework.webflow</groupId> <artifactId>spring-js</artifactId> <version>2.0.9.RELEASE</version> </dependency>


El URLRewrite es una especie de "hack" si quieres llamarlo así. A lo que se reduce es a que estás reinventando la rueda; Como ya existen soluciones existentes. Otra cosa para recordar es Servidor HTTP = Contenido estático y Servidor de aplicaciones = contenido dinámico (así es como fueron diseñados). Al delegar las responsabilidades apropiadas a cada servidor, maximiza la eficiencia ... pero hoy en día esto probablemente sea solo una preocupación en entornos de rendimiento crítico y algo como Tomcat probablemente funcionará bien en ambos roles la mayor parte del tiempo; Pero todavía es algo a tener en cuenta, no obstante.


El problema es con URLPattern

Cambie su patrón de URL en su asignación de servlet de "/" a "/ *"


En Spring 3.0.x agregue lo siguiente a su servlet-config.xml (el archivo que se configura en web.xml como contextConfigLocation. Debe agregar el espacio de nombres mvc también, pero solo busque en Google si no sabe cómo hacerlo). !;)

Funciona para mi

<mvc:default-servlet-handler/>

Saludos

Ayub Malik


Encontré una forma de evitarlo utilizando el filtro de urlrewrite de tuckey. Por favor, siéntase libre de dar una mejor respuesta si tiene una!

En web.xml:

<filter> <filter-name>UrlRewriteFilter</filter-name> <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class> </filter> <filter-mapping> <filter-name>UrlRewriteFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <servlet> <servlet-name>app</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>app</servlet-name> <url-pattern>/app/*</url-pattern> </servlet-mapping>

En urlrewrite.xml:

<urlrewrite default-match-type="wildcard"> <rule> <from>/</from> <to>/app/</to> </rule> <rule match-type="regex"> <from>^([^/.]+)$</from> <to>/app/$1</to> </rule> <outbound-rule> <from>/app/**</from> <to>/$1</to> </outbound-rule>

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


Este problema se resuelve en Spring 3.0.4.RELEASE, donde puede utilizar el elemento de configuración <mvc:resources mapping="..." location="..."/> en el archivo de configuración de Spring Dispatcher.

Compruebe la documentación de primavera


Esto hizo el verdadero trabajo en mi caso.

en web.xml:

... <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/images/*</url-pattern> <url-pattern>/css/*</url-pattern> <url-pattern>/javascripts/*</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>spring-mvc-dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>

...


Esto se puede lograr en al menos tres formas.

Soluciones :

  • exponer el html como un archivo de recursos
  • instruye al JspServlet para que también maneje las solicitudes * .html
  • escriba su propio servlet (o pase a otra solicitud de servlet existente a * .html).

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


Hay otro post de desbordamiento de pila que tiene una excelente solución .

No parece ser específico de Tomcat, es simple y funciona muy bien. He probado un par de soluciones en este post con spring mvc 3.1 pero luego tuve problemas para que mi contenido dinámico se publicara.

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

<servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/images/*</url-pattern> </servlet-mapping>


Lo resolví de esta manera:

<servlet-mapping> <servlet-name>Spring MVC Dispatcher Servlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.jpg</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.png</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.gif</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.js</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.css</url-pattern> </servlet-mapping>

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


Mi manera de resolver este problema es colocar todas sus acciones con un prefijo específico como "web" o "servicio" y configurar que todas las direcciones URL con ese prefijo sean interceptadas por el DispatcherServlet.


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

<mvc:resources mapping="/resources/**" location="/resources/" />

La sintaxis 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 sintaxis que recomiendo es la siguiente.

<mvc:resources mapping="/resources/**" location="/WEB-INF/resources/" />

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

<script type="text/javascript" src="resources/my-javascript.js"> </script>

No hace falta mencionar que solo surgió la pregunta porque quería que mi servlet de despachador de Spring (controlador frontal) interceptara todo, todo dinámico, eso es. Así que tengo lo siguiente en mi web.xml.

<servlet> <servlet-name>front-controller</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> <!-- spring automatically discovers /WEB-INF/<servlet-name>-servlet.xml --> </servlet> <servlet-mapping> <servlet-name>front-controller</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping>

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

<mvc:annotation-driven/>

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

@RequestMapping("/")

Espero que esto ayude.


Para la configuración de primavera basada en Java, puede utilizar lo siguiente

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

Más Info @ WebMvcConfigurerAdapter que define los métodos de devolución de llamada para personalizar la configuración basada en Java para Spring MVC habilitado 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"); }


Sé que hay algunas configuraciones para usar los contenidos estáticos, pero mi solución es que solo creo una carpeta de aplicaciones web masivas dentro de su Tomcat. Esta "aplicación web masiva" solo sirve todos los contenidos estáticos sin servir aplicaciones. Esta es una solución fácil y sin dolor para servir contenidos estáticos a su aplicación web de Spring.

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

  1. springapp : solo ejecuta la aplicación web de Spring sin contenido estático como imgs, js o css. (dedicado a aplicaciones de primavera).
  2. recursos : sirve solo los contenidos estáticos sin JSP, servlet o cualquier tipo de aplicación web java. (dedicado a contenidos estáticos)

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. Pongo a "nadie" en la restricción para que la página genere "403 error prohibido" cuando las personas intentaron acceder a la ruta de contenidos estáticos.

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 contenidos estáticos. Para descubrir esto, simplemente haga clic derecho en cualquier contenido estático y verifique su URI.


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 o archivos jQuery encontrados.

Acabo de agregar asignaciones al servlet "predeterminado". Se agregó lo siguiente al archivo web.xml:

<servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.css</url-pattern> </servlet-mapping> <servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>*.js</url-pattern> </servlet-mapping>

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

Una vez más, 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 muy seguro de lo que es para otros servidores.


Tuve el mismo problema y encontré la respuesta de Joris muy útil. Pero además necesito añadir

<mvc:annotation-driven />

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


Utilicé ambas formas: urlrewrite y anotación basadas en spring mvc 3.0.x, y descubrí que el enfoque basado en anotación es el más adecuado.

<annotation-driven /> <resources mapping="/resources/**" location="/resources/" />

En el caso de urlrewrite, se deben definir muchas reglas y, en algún momento, también se obtiene una excepción de clase no encontrada para UrlRewriteFilter, ya que se proporcionó la dependencia para ello. Descubrí que está ocurriendo debido a la presencia de dependencia transitiva, por lo que nuevamente un paso aumentará y tendré que excluir esa dependencia de pom.xml usando

<exclusion></exclusion> tags.

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


<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <mvc:default-servlet-handler/> </beans>

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

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