web-dev-qa-db-fra.com

À l'aide de Spring, mappage à la racine dans web.xml, les ressources statiques sont introuvables

Ce que j'essaie de faire, c'est de mapper les demandes à la racine du servlet (terminologie correcte?). J'en suis au point où les URL sont mappées pour une vue correcte, mais tout le contenu statique - css, javascript, images - qui fait partie de la page est introuvable.

Donc, dans mon web.xml, ma balise de servlet ressemble à ceci

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

Mon contrôleur ressemble à ceci:

@RequestMapping("/shop")
public class TheShopController extends MyBaseController {

    public static String VIEW = "Tile.Shop";

    @Override
    @RequestMapping(method = RequestMethod.GET)
    protected ModelAndView processRequest(HttpServletRequest req, HttpServletResponse resp) {
        ModelAndView mav = new ModelAndView(VIEW);
        return mav;
    }

}

MyBaseController est très simple. Cela ressemble à ceci:

public abstract class MyBaseController extends AbstractController {

    protected Logger log = Logger.getLogger(getClass());

    @Override
    protected ModelAndView handleRequestInternal(HttpServletRequest req, HttpServletResponse resp) 
        throws Exception {

        ModelAndView mav = processRequest(req, resp);
        return mav;
    }

    protected abstract ModelAndView processRequest(HttpServletRequest req, HttpServletResponse resp);
}

J'utilise des tuiles dans ma couche d'affichage. Ma configuration est la suivante:

/WEB-INF/tiles-defs.xml

Comme je l'ai mentionné, les vues sont trouvées mais les ressources statiques qui sont un port de la page sont introuvables. Voici quelques exemples de déconnexion typiques:

24-01-2010 17: 25: 01,777 DEBUG [http-8080-7] servlet.DispatcherServlet (DispatcherServlet.Java:690) - DispatcherServlet avec le nom 'springapp' traitant la demande GET pour [/springapp/static/css/account.css ] 2010-01-24 17: 25: 01,778 WARN [http-8080-4] servlet.DispatcherServlet (DispatcherServlet.Java:962) - Aucun mappage trouvé pour la requête HTTP avec l'URI [/springapp/static/css/shop.css] dans DispatcherServlet avec le nom 'springapp' 2010-01-24 17: 25: 01,778 DEBUG [http-8080-6] servlet.FrameworkServlet (FrameworkServlet.Java:677) - Demande terminée avec succès 2010-01-24 17: 25: 01,778 WARN [http-8080-5] servlet.DispatcherServlet (DispatcherServlet.Java:962) - Aucun mappage trouvé pour la demande HTTP avec l'URI [/springapp/static/css/offers.css] dans DispatcherServlet avec le nom 'springapp' 2010-01-24 17: 25: 01,778 WARN [http-8080-3] servlet.DispatcherServlet (DispatcherServlet.Java:962) - Aucun mappage trouvé pour la requête HTTP avec l'URI [/springapp/static/css/scrollable-buttons.css] dans DispatcherServlet avec le nom 'spri ngapp '

Aller à http: // localhost: 8080/springapp/shop fonctionne bien mais le CSS et les images sont manquants.

Je pense que l'utilisation de Tiles complique en quelque sorte les choses, mais je suis réticent à m'en débarrasser. Je me demande si je dois ajuster ma configuration de résolution de vue doit être modifiée d'une manière ou d'une autre? Enchaîner les résolveurs de vue peut-être? Je ne suis tout simplement pas expérimenté dans ce domaine.

29
richever

Le problème est que les demandes de contenu statique vont au dispatcherServlet, car il est mappé en tant que <url-pattern>/</url-pattern>. C'est un problème très courant dans les applications avec des URL "RESTful" (c'est-à-dire sans aucun préfixe dans le mappage DispatcherServlet).

Il existe plusieurs façons de résoudre ce problème:


Depuis Spring 3.x, la façon préférée d'accéder aux ressources statiques est d'utiliser <mvc:resources>: web.xml:

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

Configuration de printemps:

<!-- Handles GET requests for /resources/** by efficiently serving static content 
    in the ${webappRoot}/resources dir --> 
<mvc:resources mapping="/resources/**" location="/resources/" /> 

Voir aussi Simplifications MVC au printemps


1. Utiliser le filtre de réécriture d'URL
Voir mvc-basic exemple ici

2. Définissez un préfixe pour le servlet default:

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

Autrement dit, demande de /static/images/image.png renverra le fichier nommé /images/image.png Cependant, cette méthode est incompatible entre les différents conteneurs de servlets (ne fonctionne pas dans Jetty), voir les solutions de contournement ici

3. Définissez les extensions de contenu statique pour le servlet default:

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

4. N'utilisez pas d'URL RESTful, utilisez des URL avec préfixe:

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

5. N'utilisez pas d'URL RESTful, utilisez des URL avec l'extension:

<servlet-mapping> 
    <servlet-name>springapp</servlet-name> 
    <url-pattern>*.do</url-pattern> 
</servlet-mapping>
61
axtavt

Quelqu'un at-il envisagé d'utiliser ceci:

<!-- Allows for mapping the DispatcherServlet to "/" by forwarding static resource requests to the container's default Servlet -->
<mvc:default-servlet-handler/>

Voici les derniers documents du printemps à ce sujet: http://static.springsource.org/spring/docs/3.1.2.RELEASE/spring-framework-reference/htmlsingle/spring-framework-reference.html#mvc -default-servlet-handler

5
Solubris

Comme alternative au numéro de solution proposé (2, servlet par défaut qui se comporte différemment d'un conteneur de servlet à un conteneur de servlet), je recommanderais de jeter un œil au Resource Servlet (org.springframework.js.resource.ResourceServlet) du projet Spring Webflow.

Pour plus de détails, veuillez consulter Comment gérer le contenu statique dans Spring MVC?

4
ngeek

J'ai le même problème mais au lieu d'utiliser spring, je fais mon petit filtre qui redirige root vers ma page de démarrage comme ça:

    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse res = (HttpServletResponse) response;

    String pageName = req.getServletPath();

    if(pageName.equals("/")) {
        res.sendRedirect( req.getContextPath() + "/start" );
    } else {
        chain.doFilter(request, response);
    }

C'est peut-être une astuce, mais cela semble fonctionner correctement avec un petit code. Allez ici pour plus d'informations sur les filtres http://www.Oracle.com/technetwork/Java/filters-137243.html

1
Nereis