Spring Boot not serving static content

I can't get my Spring-boot project to serve static content.

I've placed a folder named static under src/main/resources. Inside it I have a folder named images. When I package the app and run it, it can't find the images I have put on that folder.

I've tried to put the static files in public, resources and META-INF/resources but nothing works.

If I jar -tvf app.jar I can see that the files are inside the jar on the right folder: /static/images/head.png for example, but calling: http://localhost:8080/images/head.png, all I get is a 404

Any ideas why spring-boot is not finding this? (I'm using 1.1.4 BTW)


Solution 1:

Not to raise the dead after more than a year, but all the previous answers miss some crucial points:

  1. @EnableWebMvc on your class will disable org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration. That's fine if you want complete control but otherwise, it's a problem.

  2. There's no need to write any code to add another location for static resources in addition to what is already provided. Looking at org.springframework.boot.autoconfigure.web.ResourceProperties from v1.3.0.RELEASE, I see a field staticLocations that can be configured in the application.properties. Here's a snippet from the source:

    /**
     * Locations of static resources. Defaults to classpath:[/META-INF/resources/,
     * /resources/, /static/, /public/] plus context:/ (the root of the servlet context).
     */
    private String[] staticLocations = RESOURCE_LOCATIONS;
    
  3. As mentioned before, the request URL will be resolved relative to these locations. Thus src/main/resources/static/index.html will be served when the request URL is /index.html. The class that is responsible for resolving the path, as of Spring 4.1, is org.springframework.web.servlet.resource.PathResourceResolver.

  4. Suffix pattern matching is enabled by default which means for a request URL /index.html, Spring is going to look for handlers corresponding to /index.html. This is an issue if the intention is to serve static content. To disable that, extend WebMvcConfigurerAdapter (but don't use @EnableWebMvc) and override configurePathMatch as shown below:

    @Override
    public void configurePathMatch(PathMatchConfigurer configurer) {
        super.configurePathMatch(configurer);
    
        configurer.setUseSuffixPatternMatch(false);
    }
    

IMHO, the only way to have fewer bugs in your code is not to write code whenever possible. Use what is already provided, even if that takes some research, the return is worth it.

Edit July 2021:

  1. WebMvcConfigurerAdapter has been deprecated since Spring 5. Implement WebMvcConfigurer and annotate with @Configuration.

Solution 2:

Unlike what the spring-boot states, to get my spring-boot jar to serve the content: I had to add specifically register my src/main/resources/static content through this config class:

@Configuration
public class StaticResourceConfiguration implements WebMvcConfigurer {

    private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
            "classpath:/META-INF/resources/", "classpath:/resources/",
            "classpath:/static/", "classpath:/public/" };

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

Solution 3:

I had a similar problem, and it turned out that the simple solution was to have my configuration class extend WebMvcAutoConfiguration:

@Configuration
@EnableWebMvc
@ComponentScan
public class ServerConfiguration extends WebMvcAutoConfiguration{
}

I didn't need any other code to allow my static content to be served, however, I did put a directory called public under src/main/webapp and configured maven to point to src/main/webapp as a resource directory. This means that public is copied into target/classes, and is therefore on the classpath at runtime for spring-boot/tomcat to find.