Serving static resources in Spring

If you are using Spring MVC you may want Spring to handle all non-static requests through Spring controllers. So you set up the DispatcherServlet and specify / as the mapping which makes it the default servlet, so all requests that doesn’t match another servlet’s mapping will go through the DispatcherServlet. To achieve this, in your web.xml you set up something like this:

<servlet>
    <servlet-name>mvc-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/dispatcher-servlet.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

However, by defining the DispatcherServlet this way you’ll notice that trying to access your static resources (images, css, js etc.) will result in 404 errors. This is because the request for these files will also go through the DispatcherServlet and it won’t find a suitable controller to serve them.

To counter this, you have two options.

1. Option: Specify the mvc:default-servlet-handler element

In the context xml of your DispatcherServlet specifiy the following:

<mvc:default-servlet-handler />

The result of this is that if a request cannot be handled by the DispatcherServlet, then it will be handled by the default servlet of the servlet container (e.g. tomcat). In tomcat this default servlet is defined in the conf/web.xml file and is able to serve static resources.

We also need another annotation in the same file:

<mvc:annotation-driven />

This is needed because Spring has some smart defaults (like finding classes with @Controller annotations and dispatching request to methods in them) if we don’t add any custom config. But with the addition of <mvc:default-servlet-handler /> we disabled this default config and must explicitly enable support for these otherwise default features.

2. Option: Use the mvc:resources element

<mvc:resources  mapping="/css_files/**" location="/css/"/>

The <mvc:resorces> element specifies that all requests matching the mapping attribute will be served from the place specified in the location attribute. So for example when requesting /css_files/style.css, Spring will look for it at /css/style.css. You can have any number of this element. The serving of resources is done by the ResourceHttpRequestHandler element.

In this case you also need to use the <mvc:annotation-driven /> for the same reason as in the previous option.

References