web-dev-qa-db-fra.com

Printemps 4 - addResourceHandlers ne résout pas les ressources statiques

La structure de répertoire de mon projet maven spring est présentée ci-dessous. J'utilise une configuration basée sur des annotations Spring-4. Je configure les ressources comme ci-dessous. J'ai essayé de nombreuses manières suggérées dans de nombreuses questions Stackoverflow et d'autres sites Web. 

Printemps 4 chargement de ressources statiques

http://imwill.com/spring-mvc-4-add-static-resources-by-annotation/#.U5GZlXKs9i4

Mais les fichiers jsp ne pouvaient pas charger les ressources, toutes les demandes de contenu statique retournent une erreur 404. J'ai essayé ces choses en jsp, 

 <link href="resources/css/bootstrap.css" rel="stylesheet" media="screen">
 <link href="/resources/css/bootstrap.css" rel="stylesheet" media="screen">
 <link href="css/bootstrap.css" rel="stylesheet" media="screen">

EDIT: J'utilise servlet 2.5 car je ne peux pas pour l'instant mettre à niveau mon projet de JBoss 5 vers des versions plus récentes. JBoss5 ne supporte pas les servlets 3, et est-ce important?

@Configuration
@ComponentScan("com.mgage.mvoice")
public class MyAppWebConfig extends WebMvcConfigurerAdapter {
     public void addResourceHandlers(ResourceHandlerRegistry registry) {  
        // I tried these many combinations separately.

        ResourceHandlerRegistration resourceRegistration = registry
            .addResourceHandler("resources/**");
        resourceRegistration.addResourceLocations("/resources/**");
        registry.addResourceHandler("/css/**").addResourceLocations("/css/**");
        registry.addResourceHandler("/img/**").addResourceLocations("/img/**");
        registry.addResourceHandler("/js/**").addResourceLocations("/js/**");
        registry.addResourceHandler("/resources/**")
                .addResourceLocations("classpath:/resources/"); 
              // do the classpath works with the directory under webapp?
     }

}

Project structure

24
Vijay Veeraraghavan

cela a fonctionné, 

   registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");

et dans les fichiers jsp je me suis référé aux ressources statiques comme 

<link href="resources/css/bootstrap.css" rel="stylesheet" media="screen">
15

Je suppose que c'est un peu tard, mais je venais tout juste de faire face à un problème similaire. Après plusieurs jours de lutte, il s’est finalement avéré que mon DispatcherServlet n’était pas configuré pour gérer la demande. Par conséquent, les ressources n’étaient jamais consultées. J'espère donc que d'autres trouveront cette réponse utile.

Si la servlet du répartiteur à laquelle vous donnez la classe de configuration ci-dessus est mappée non sur la racine ("/") mais sur un mot supérieur (par exemple, "/ data /"), vous risquez de rencontrer le même problème.

Supposons que je dispose d'un mappage en tant que "/ data/*" pour mon servlet de répartiteur. Alors mes appels ressemblent

http://localhost:8080/myWebAppContext/data/command

et j’ai pensé que si j’ai une cartographie des ressources, par ex. "/ content/**/*", alors j'y ai accès en tant que

http://localhost:8080/myWebAppContent/content/resourcePath

mais ce n'est pas vrai, je devrais utiliser

http://localhost:8080/myWebAppContent/data/content/resourcePath

au lieu. Cela n’était pas clair pour moi, et comme la plupart des exemples utilisent la racine "/" pour le mappage de la servlet du répartiteur, le problème ne se posait donc pas. En réfléchissant plus tard, j'aurais dû le savoir plus tôt -/data/indique que le DispatcherServlet doit évaluer l'appel et que le contenu/indique au servlet qu'un gestionnaire de ressources est le "contrôleur".

Mais je tiens à préciser très clairement dans mon interface (angularJs) si je recherche des données (via les services REST) ou un contenu (renvoi de textes en clair). Les données proviennent d'une base de données, mais le contenu provient de fichiers (par exemple, des documents pdf). Par conséquent, j'ai décidé d'ajouter deux correspondances à la servlet de répartiteur:

public class MidtierWebConfig implements WebApplicationInitializer {

@Override
public void onStartup(ServletContext servletContext) throws ServletException {

    AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
    rootContext.register(MidtierAppConfig.class);

    servletContext.addListener(new ContextLoaderListener(rootContext));

    AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
    dispatcherContext.register(MidtierDispatcherConfig.class);

    Dynamic netskolaDispatcher = servletContext.addServlet(
        "dispatcher",
        new DispatcherServlet(dispatcherContext)
    );
    netskolaDispatcher.setLoadOnStartup(1);
    netskolaDispatcher.addMapping("/data/*");
    netskolaDispatcher.addMapping("/content/*");
}

}

La classe MidtierAppConfig est vide, mais MidtierDispatcherConfig définit les ressources statiques:

@Configuration
@ComponentScan("my.root.package")
@EnableWebMvc
public class MidtierDispatcherConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry
            .addResourceHandler("/courses/**/*")
            .addResourceLocations("/WEB-INF/classes/content/")
        ;
    }
}

Maintenant, lorsque je veux avoir accès à mon @ Contrôleur, j'utilise le préfixe/data /, et lorsque je veux accéder à mes ressources, j'utilise le préfixe/content /. L’avertissement est que si j’ai une classe @RequestMapping ("/ app") qui a une méthode @RequestMapping ("/ about"), alors les données/app/about et le contenu/app/about appellent uniquement cette méthode ( et sans réellement essayer, je suppose que je pourrais accéder aux ressources sous/app/courses/whatEverPath aussi), car le répartiteur liste à la fois "data /" et "content /", et analyse uniquement le reste de l'URL ("app/about "dans les deux cas) pour trouver le @Controller approprié.

Quoi qu’il en soit, la solution actuelle à laquelle je suis parvenue est suffisamment satisfaisante pour moi, je la laisserai donc telle quelle.

12
Ivan Ketler

Cela a fonctionné pour moi. Fichiers disponibles au /resources/js/select.js. Attention, il ne vous manque pas l'annotation @EnableWebMvc .... 

@EnableWebMvc
@EnableTransactionManagement
public class ApplicationContextConfig extends WebMvcConfigurerAdapter {

    @Bean(name = "viewResolver")
    public InternalResourceViewResolver getViewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/views/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**")
        .addResourceLocations("/resources/");
    }
}
6
kundan

Il est possible de simplifier l'URI de la page Web simplement pour contenir le nom de fichier d'une ressource:
<link href="bootstrap.css" rel="stylesheet" media="screen">
Une configuration appropriée pourrait être la suivante: 

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("*.css").addResourceLocations("/resources/css/");
}

Spring concatène la chaîne '/ resources/css /' avec le nom de fichier extrait de l'URI afin d'identifier l'emplacement réel d'une ressource.

0
beemaster