201 votes

Comment gérer le contenu statique dans Spring MVC ?

Je développe une application web en utilisant Spring MVC 3 et j'ai le problème suivant DispatcherServlet capturer toutes les requêtes vers '/' comme suit (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>

Cela fonctionne comme prévu, mais comment gérer le contenu statique ? Auparavant, avant d'utiliser les URL RESTful, j'aurais attrapé tous les *.html par exemple et je les aurais envoyés à l'URL DispatcherServlet mais aujourd'hui c'est une autre paire de manches.

J'ai un dossier /static/ qui comprend /styles/, /js/, /images/, etc. et je voudrais exclure /static/* de la liste de contrôle. DispatcherServlet .

J'ai pu faire fonctionner les ressources statiques en procédant de la sorte :

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

Mais je veux qu'il y ait de belles URL (c'est pour cela que j'utilise Spring MVC 3) et que la page d'atterrissage ne soit pas www.domain.com/app/.

Je ne veux pas non plus d'une solution couplée à tomcat ou à un autre conteneur de servlets, et comme il s'agit d'un trafic (relativement) faible, je n'ai pas besoin d'un serveur web (comme apache httpd) à l'avant.

Existe-t-il une solution propre à ce problème ?

1 votes

0 votes

@hamo Un sujet connexe : stackoverflow.com/questions/34279705/

271voto

Joris Points 2048

Comme j'ai passé beaucoup de temps sur ce problème, j'ai pensé partager ma solution. Depuis spring 3.0.4, il y a un paramètre de configuration qui s'appelle <mvc:resources/> (plus d'informations à ce sujet sur le site site web de documentation de référence ) qui peut être utilisée pour servir des ressources statiques tout en utilisant la DispatchServlet sur la racine de votre site.

Pour ce faire, utilisez une structure de répertoire qui ressemble à ce qui suit :

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

Le contenu des fichiers devrait ressembler à ce qui suit :

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>

WebContent/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>

WebContent/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" />" />

13 votes

Cet exemple devrait figurer dans le guide de l'utilisateur de Spring - c'est le meilleur que j'ai vu sur ce sujet. Merci Joris !

0 votes

Cela a définitivement fait l'affaire pour moi - le simple conseil de rozky est ce que j'ai commencé à faire, mais pour une raison quelconque, toute page, autre que ma page d'accueil, rendait les ressources-URL relatives à la page - en suivant ce conseil, elles sont rendues relatives au context-Root de mon application à la place - et cela fonctionne parfaitement ! Merci à tous !

0 votes

Merci ! Je m'arrachais les cheveux jusqu'à ce que je change la ligne : <mvc:resources mapping="/resources/**" location="/, classpath:/META-INF/web-resources/" /> en <mvc:resources mapping="/resources/**" location="/resources/" />

46voto

rozky Points 1385

Ce problème est résolu dans spring 3.0.4.RELEASE où vous pouvez utiliser <mvc:resources mapping="..." location="..."/> dans votre fichier de configuration de Spring Dispatcher.

Vérifier Documentation sur le printemps

5 votes

Bien qu'elle ne soit pas "fausse", cette réponse est trop brève parce que la documentation de Spring (à laquelle vous avez fait référence dans votre réponse) semble manquer quelque chose. Consultez la réponse de Joris pour une réponse plus complète... non pas parce qu'elle est longue mais parce qu'elle mentionne l'utilisation de <c:url ...> que ni votre réponse ni la dox de Spring ne mentionnent -- et qui s'est avérée être une partie critique de la solution.

38voto

Ayub Malik Points 291

Dans Spring 3.0.x, ajoutez ce qui suit à votre servlet-config.xml (le fichier qui est configuré dans web.xml comme contextConfigLocation. Vous devez également ajouter l'espace de noms mvc, mais il vous suffit de chercher sur Google si vous ne savez pas comment faire !

Cela me convient parfaitement

<mvc:default-servlet-handler/>

0 votes

Lorsque j'ajoute cette ligne, j'obtiens : org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException : Line 31 in XML document from class path resource [META-INF/spring/application-context.xml] is invalid ; nested exception is org.xml.sax.SAXParseException ; lineNumber : 31 ; columnNumber : 35 ; cvc-complex-type.2.4.c : Le joker correspondant est strict, mais aucune déclaration ne peut être trouvée pour l'élément 'mvc:default-servlet-handler'.

0 votes

Veillez à respecter l'ordre du gestionnaire lorsque vous avez d'autres résolveurs de vues.

20voto

user243397 Points 121

Si je comprends bien votre problème, je pense avoir trouvé une solution à votre problème :

J'ai eu le même problème où la sortie brute était affichée sans qu'aucun style css, javascripts ou fichiers jquery n'aient été trouvés.

Je viens d'ajouter des mappings au servlet "default". Le texte suivant a été ajouté au fichier 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>

Cela devrait permettre de filtrer les demandes de fichiers javascript et css provenant de l'objet DispatcherRequest.

Encore une fois, je ne sais pas si c'est ce que vous recherchez, mais cela a fonctionné pour moi. Je pense que "default" est le nom du servlet par défaut dans JBoss. Je ne sais pas trop ce qu'il en est pour les autres serveurs.

1 votes

En fait, je ne veux pas utiliser le servlet par défaut, qui me couple à jboss/tomcat.

0 votes

@hamo pourquoi est-ce un problème ? (c'est une vraie question, pas une réponse argumentée). Vous aurez besoin de faire tourner le serveur (jboss/tomcat/jetty) de toute façon pour que Spring fonctionne, n'est-ce pas ?

3 votes

Et vous pouvez ajouter tous les <url-pattern> à l'intérieur du même <servlet-mapping>

16voto

user1788698 Points 81

Il y a un autre post de stack overflow qui a un excellente solution .

Il ne semble pas être spécifique à Tomcat, il est simple et fonctionne très bien. J'ai essayé quelques unes des solutions proposées dans ce billet avec spring mvc 3.1 mais j'ai eu des problèmes pour faire servir mon contenu dynamique.

En bref, il s'agit d'ajouter un mappage de servlet comme suit :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X