Comment gérer le contenu statique en MVC printemps?
je développe une webapp en utilisant le ressort MVC 3 et ai le DispatcherServlet
attraper toutes les requêtes à '/' comme ainsi (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>
maintenant cela fonctionne comme annoncé, mais comment puis-je gérer le contenu statique? Auparavant, avant D'utiliser les URLs RESTful, j'aurais attrapé tous les *.html par exemple et envoyé cela au DispatcherServlet
, mais maintenant c'est un jeu de balle différent.
j'ai un répertoire/ static / qui inclut/ styles/, / js/, / images / etc et je voudrais exclure / static / * du DispatcherServlet
.
maintenant je pouvais obtenir des ressources statiques de travail quand je l'ai fait:
<servlet-mapping>
<servlet-name>app</servlet-name>
<url-pattern>/app/</url-pattern>
</servlet-mapping>
mais je veux qu'il ait de belles URLs (le point de moi en utilisant MVC printemps 3) pas la page d'accueil étant www.domain.com/app /
Je ne veux pas non plus d'une solution couplée à tomcat ou à tout autre conteneur servlet, et parce que c'est (relativement) peu de trafic Je n'ai pas besoin d'un serveur web (comme apache httpd) en face.
y a-t-il une solution propre à cela?
22 réponses
comme j'ai passé beaucoup de temps sur cette question, j'ai pensé que je partagerais ma solution. Depuis le printemps 3.0.4, il y a un paramètre de configuration qui s'appelle <mvc:resources/>
(plus d'informations à ce sujet sur le site documentation de référence ) qui peut être utilisé pour servir des ressources statiques tout en utilisant le DispatchServlet sur la racine de votre site.
pour utiliser ceci, utilisez une structure de répertoire qui ressemble à la suivante:
src/
springmvc/
web/
MyController.java
WebContent/
resources/
img/
image.jpg
WEB-INF/
jsp/
index.jsp
web.xml
springmvc-servlet.xml
le contenu des fichiers doit ressembler à:
src/spring mvc/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" />" />
Espérons que cela aide :-)
ce problème est résolu au printemps 3.0.4.Libérer où vous pouvez utiliser
<mvc:resources mapping="..." location="..."/>
élément de configuration dans votre fichier de configuration de régulateur de vitesse.
Vérifier Printemps De La Documentation
Au Printemps 3.0.x ajouter ce qui suit à votre servlet-config.xml (le fichier qui est configuré dans web.xml comme contextConfigLocation. Vous devez ajouter le namespace mvc aussi bien que google pour cela si vous ne savez pas comment! ;)
Qui fonctionne pour moi
<mvc:default-servlet-handler/>
concerne
Ayub Malik
si je comprends bien votre problème, je pense que j'ai trouvé une solution à votre problème:
j'ai eu le même problème où la production brute a été montrée sans les styles css, javascripts ou les fichiers jquery trouvés.
je viens d'ajouter des mappings au servlet" default". Ce qui suit a été ajouté au site web.fichier 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>
ceci devrait filtrer les requêtes javascript et css de l'objet DispatcherRequest.
encore une fois, je ne sais pas si c'est ce que vous cherchez, mais ça a marché pour moi. Je pense que "par défaut" est le nom par défaut de la servlet dans JBoss. Pas trop sûr de ce que c'est pour les autres serveurs.
il y a un autre poste de débordement de pile qui a une excellente solution .
Il ne semble pas être spécifique à Tomcat, est simple et fonctionne très bien. J'ai essayé quelques-unes des solutions dans ce post avec printemps mvc 3.1, mais a ensuite eu des problèmes pour obtenir mon contenu dynamique servi.
en bref, il est dit d'ajouter un servlet mapping comme ceci:
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/images/*</url-pattern>
</servlet-mapping>
je viens de m'attaquer à ce problème au printemps MVC 3.0 et je suis d'abord allé avec L'option UrlRewriteFilter. Cependant, je n'étais pas satisfait de cette solution car elle "ne se sentait pas bien" (je ne suis pas le seul - voir le lien ci-dessus vers les Forums de printemps où le mot "hack" apparaît à quelques reprises).
donc j'ai trouvé une solution similaire à" Unknown (Google) " ci-dessus mais j'ai emprunté l'idée d'avoir tout le contenu statique servi de / static/ (pris du Roo de printemps version de l'application Pet Store). Le servlet "par défaut" ne fonctionnait pas pour moi, mais le servlet Spring Webflow ResourceServlet l'a fait (également tiré de L'application générée par 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>
le seul changement que j'ai fait à JSPs était d'ajouter le /static/ path aux URLs pour CSS, JS et images. Par exemple: "${pageContext.demande.contextPath}/static/css/écran.CSS."
pour les utilisateurs Maven la dépendance pour "org.springframework.js.ressources.ResourceServlet "is:
<dependency>
<groupId>org.springframework.webflow</groupId>
<artifactId>org.springframework.js</artifactId>
<version>2.0.8.RELEASE</version>
</dependency>
j'ai trouvé un moyen de l'contourner en utilisant l'urlrewritefilter de tuckey. N'hésitez pas à donner une meilleure réponse si vous en avez un!
dans 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>
dans urlrewrite.xml:
<urlrewrite default-match-type="wildcard">
<rule>
<from>/</from>
<to>/app/</to>
</rule>
<rule match-type="regex">
<from>^([^\.]+)$</from>
<to>/app/</to>
</rule>
<outbound-rule>
<from>/app/**</from>
<to>/</to>
</outbound-rule>
Cela signifie que tout uri avec un '."(style.css par exemple) ne sera pas réécrite.
ma propre expérience avec ce problème est comme suit. La plupart des pages Web et des livres relatifs au printemps semblent suggérer que la syntaxe la plus appropriée est la suivante.
<mvc:resources mapping="/resources/**" location="/resources/" />
la syntaxe ci-dessus suggère que vous pouvez placer vos ressources statiques (CSS, JavaScript, images) dans un dossier nommé" resources " dans la racine de votre application, i.e. /webapp/resources/.
cependant, d'après mon expérience (J'utilise Eclipse et le plugin Tomcat), le la seule approche qui fonctionne est si vous placez votre dossier de ressources à l'intérieur de WEB_INF (ou META-INF). Ainsi, la syntaxe que je recommande est la suivante.
<mvc:resources mapping="/resources/**" location="/WEB-INF/resources/" />
dans votre JSP (ou un document similaire) , référez-vous à la ressource comme suit:
<script type="text/javascript"
src="resources/my-javascript.js">
</script>
inutile de mentionner que toute la question s'est posée uniquement parce que je voulais que mon servlet de régulateur à ressort (contrôleur avant) intercepte tout, tout ce qui est dynamique, c'est-à-dire. Donc, j'ai l' la suite sur mon site internet.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>
enfin, puisque j'utilise les meilleures pratiques actuelles, j'ai ce qui suit dans mon servlet de contrôleur front xml (voir ci-dessus).
<mvc:annotation-driven/>
et j'ai ce qui suit dans mon implémentation actuelle de controller, pour m'assurer que j'ai une méthode par défaut pour traiter toutes les requêtes entrantes.
@RequestMapping("/")
j'espère que cela aidera.
j'ai eu le même problème et J'ai trouvé la réponse de Joris très utile. Mais en plus je dois ajouter
<mvc:annotation-driven />
au fichier de configuration servlet. Sans cela, la cartographie des ressources ne fonctionnera pas et tous les gestionnaires cesseront de fonctionner. Espérons que cela aidera quelqu'un.
L'URLRewrite est une sorte de" hack " si vous voulez l'appeler comme ça. Il s'agit de réinventer la roue, car il existe déjà des solutions. Une autre chose à retenir est Http Server = contenu statique & App server = contenu dynamique (c'est ainsi qu'ils ont été conçus). En déléguant les responsabilités appropriées à chaque serveur, vous maximisez l'efficacité... mais aujourd'hui, ce n'est probablement qu'une préoccupation dans un environnement critique de performance et quelque chose comme Tomcat fonctionnerait très probablement bien dans les deux rôles la plupart du temps, mais c'est encore quelque chose à garder à l'esprit.
Je l'ai résolu de cette façon:
<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>
ça marche sur Tomcat et ofcourse Jboss. Cependant, à la fin, j'ai décidé d'utiliser la solution Printemps (comme mentionné par rozky) qui est beaucoup plus portable.
à partir du printemps 3, toutes les ressources doivent être cartographiées d'une manière différente. Vous devez utiliser la balise pour indiquer l'emplacement des ressources.
exemple:
<mvc:resources mapping="/resources/**" location="/resources/" />
de cette façon, vous dirigez le servlet du répartiteur à regarder dans les ressources du répertoire pour rechercher le contenu statique.
ma façon de résoudre ce problème est de placer toutes vos actions avec un préfixe spécifique comme" web "ou" service " et configurer que toutes les url avec ce préfixe seront interceptées par le DispatcherServlet.
j'ajoute juste trois règles avant la règle par défaut de spring (/**) à l'urlrewritefilter de tuckey (urlrewrite.xml) pour résoudre le problème
<?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/</to>
</rule>
<rule>
<from>/styles/**</from>
<to>/styles/</to>
</rule>
<rule>
<from>/images/**</from>
<to>/images/</to>
</rule>
<rule>
<from>/**</from>
<to>/app/</to>
</rule>
<outbound-rule>
<from>/app/**</from>
<to>/</to>
</outbound-rule>
</urlrewrite>
je sais qu'il y a quelques configurations pour utiliser les contenus statiques, mais ma solution est que je viens de créer un dossier Web-application en vrac dans votre tomcat. Cette "webapp en vrac"ne sert que tous les contenus statiques sans applications. C'est la solution sans douleur et facile pour servir le contenu statique à votre webapp printemps réel.
par exemple, j'utilise deux dossiers webapp sur mon tomcat.
- springapp : il n'exécute qu'une application web à ressort sans contenu statique comme imgs, js ou css. (dédié pour le printemps apps.)
- resources : il ne sert que les contenus statiques sans JSP, servlet, ou toute autre sorte d'application Web java. (dédié aux contenus statiques)
si je veux utiliser javascript, je n'ai qu'à ajouter L'URI de mon fichier javascript.
EX 1519180920" /ressources/chemin/vers/js/myjavascript.js
pour les images statiques, j'utilise la même méthode.
EX> /ressources/chemin/vers/img/myimg.jpg
enfin, j'ai mis " security-constraint " sur mon tomcat pour bloquer l'accès au répertoire réel. J'ai mis" nobody "user-roll à la contrainte de sorte que la page génère" 403 forbidden error " quand les gens ont essayé d'accéder au chemin des contenus statiques.
jusqu'à présent, il fonctionne très bien pour moi. J'ai également remarqué que de nombreux sites Web populaires comme Amazon, Twitter, et Facebook, ils utilisent différents URI pour servir des contenus statiques. Pour le savoir, cliquez avec le bouton droit de la souris sur n'importe quel contenu statique et vérifiez leur URI.
j'ai utilisé les deux façons qui est urlrewrite et annotation basée dans le printemps mvc 3.0.x et a constaté que l'annotation basée sur l'approche la plus appropriée est
<annotation-driven />
<resources mapping="/resources/**" location="/resources/" />
dans le cas d'urlrewrite,doivent définir beaucoup de règle et un certain temps aussi obtenir classe not found exception pour UrlRewriteFilter comme déjà fourni la dépendance pour elle. J'ai constaté que cela se produit en raison de la présence de la dépendance transitive, donc encore une fois un pas sera augmenté et ont exclure cette dépendance de pom.xml à l'aide de
<exclusion></exclusion> tags.
donc l'approche basée sur l'annotation sera la bonne chose.
Cela fait le vrai travail dans mon cas
dans 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>
...
après avoir rencontré et passé par le même processus de prise de décision décrit ici, j'ai décidé d'aller avec la proposition ResourceServlet qui fonctionne assez bien.
notez que vous obtenez plus d'informations sur la façon d'utiliser webflow dans votre processus de construction maven ici: http://static.springsource.org/spring-webflow/docs/2.0.x/reference/html/ch01s05.html
si vous utilisez le dépôt central Standard Maven est (à l'opposé du paquet springsource susmentionné):
<dependency>
<groupId>org.springframework.webflow</groupId>
<artifactId>spring-js</artifactId>
<version>2.0.9.RELEASE</version>
</dependency>
cela peut être réalisé d'au moins trois façons.
Solutions :
- exposer le html comme un fichier de ressource
- donner instruction au JspServlet de manipuler aussi *.demandes html
- ecrire votre propre servlet (ou passer à une autre demande de servlet existante à *.HTML.)
réponse dans un autre message: comment faire pour faire correspondre les demandes au fichier HTML dans MVC printemps?
le problème est avec URLPattern
changez votre motif URL sur votre servlet mapping de " / " à " / *
<?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>
et si vous voulez utiliser la configuration basée sur l'annotation utiliser le code ci-dessous
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
pour une configuration de ressort basée sur java, vous pouvez utiliser le
à l'Aide ResourceHandlerRegistry qui stocke les enregistrements de ressources des gestionnaires pour servir de ressources statiques.
More Info @ WebMvcConfigurerAdapter qui définit les méthodes de rappel pour personnaliser la configuration Java pour MVC printemps activé via @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");
}