Spring 4 - addResourceHandlers not resolving the static resources

安稳与你 提交于 2019-11-26 18:52:12

this worked,

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

and in the jsp files I referred to the static resources like

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

I guess it's a bit late, however I was facing with a similar problem just recently. After several days of wrestling, finally it turned out that my DispatcherServlet was not configured to handle the request, therefore the resources were never looked up. So I hope others will find this answer useful.

If the dispatcher servlet to that you give your config class above is mapped not to the root ("/") but to a top word (e.g. "/data/"), then you might face with the same problem.

Suppose I have a mapping as "/data/*" for my dispatcher servlet. So my calls look like

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

and I thought that if I have a resource mapping e.g. "/content/**/*", then I have access to it as

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

but it's not true, I should use

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

instead. This was not clear for me, and since most of the samples use the root "/" for the dispatcher servlet's mapping, therefore it was not an issue there. Upon considering later I should have known it earlier - /data/ tells that the DispatcherServlet should evaluate the call, and the content/ tells to the servlet that a resource handler is the "controller".

But I want to make it very clear in my frontend (angularJs) whether I look for data (via the REST services) or a content (returning plain texts). The data comes from a database, but the content comes from files (e.g. pdf docs). Therefore, I decided to add two mappings to the dispatcher servlet:

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/*");
}

}

The MidtierAppConfig class is empty, but the MidtierDispatcherConfig defines the static resources:

@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/")
        ;
    }
}

Now when I want to have access to my @Controller's, I use the /data/ prefix, and when I want to access to my resources, I use the /content/ prefix. Caveat is that if I have a @RequestMapping("/app") class which has a @RequestMapping("/about") method, then both the data/app/about and the content/app/about will call just that method (and without actually trying I guess I might access the resources as /app/courses/whatEverPath too), because the dispatcher listends to both "data/" and "content/", and analyzes only the rest of the url ("app/about" in both cases) to find the proper @Controller.

Regardless, the current solution I've reached is satisfactory enough for me, so I will leave it as it is.

This worked for me. Files available at /resources/js/select.js. Watch out that you are not missing @EnableWebMvc annotation....

@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/");
    }
}

It is possible to simplify the web page's URI just to contain the filename of a resource:
<link href="bootstrap.css" rel="stylesheet" media="screen">
An appropriate configuration might be as the following:

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

Spring concatenates '/resources/css/' string with whatever filename extracted from URI to identify the actual location of a resource.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!