How do you set cache headers in Spring MVC?

Solution 1:

I just encountered the same problem, and found a good solution already provided by the framework. The org.springframework.web.servlet.mvc.WebContentInterceptor class allows you to define default caching behaviour, plus path-specific overrides (with the same path-matcher behaviour used elsewhere). The steps for me were:

  1. Ensure my instance of org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter does not have the "cacheSeconds" property set.
  2. Add an instance of WebContentInterceptor:

    <mvc:interceptors>
    ...
    <bean class="org.springframework.web.servlet.mvc.WebContentInterceptor" p:cacheSeconds="0" p:alwaysUseFullPath="true" >
        <property name="cacheMappings">
            <props>
                <!-- cache for one month -->
                <prop key="/cache/me/**">2592000</prop>
                <!-- don't set cache headers -->
                <prop key="/cache/agnostic/**">-1</prop>
            </props>
        </property>
    </bean>
    ...
    </mvc:interceptors>
    

After these changes, responses under /foo included headers to discourage caching, responses under /cache/me included headers to encourage caching, and responses under /cache/agnostic included no cache-related headers.


If using a pure Java configuration:

@EnableWebMvc
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
  /* Time, in seconds, to have the browser cache static resources (one week). */
  private static final int BROWSER_CACHE_CONTROL = 604800;

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

See also: http://docs.spring.io/spring-security/site/docs/current/reference/html/headers.html

Solution 2:

The answer is quite simple:

@Controller
public class EmployeeController {
@RequestMapping(value = "/find/employer/{employerId}", method = RequestMethod.GET) public List getEmployees(@PathVariable("employerId") Long employerId, final HttpServletResponse response) { response.setHeader("Cache-Control", "no-cache"); return employeeService.findEmployeesForEmployer(employerId); }
}
Code above shows exactly what you want to achive. You have to do two things. Add "final HttpServletResponse response" as your parameter. And then set header Cache-Control to no-cache.

Solution 3:

org.springframework.web.servlet.support.WebContentGenerator, which is the base class for all Spring controllers has quite a few methods dealing with cache headers:

/* Set whether to use the HTTP 1.1 cache-control header. Default is "true".
 * <p>Note: Cache headers will only get applied if caching is enabled
 * (or explicitly prevented) for the current request. */
public final void setUseCacheControlHeader();

/* Return whether the HTTP 1.1 cache-control header is used. */
public final boolean isUseCacheControlHeader();

/* Set whether to use the HTTP 1.1 cache-control header value "no-store"
 * when preventing caching. Default is "true". */
public final void setUseCacheControlNoStore(boolean useCacheControlNoStore);

/* Cache content for the given number of seconds. Default is -1,
 * indicating no generation of cache-related headers.
 * Only if this is set to 0 (no cache) or a positive value (cache for
 * this many seconds) will this class generate cache headers.
 * The headers can be overwritten by subclasses, before content is generated. */
public final void setCacheSeconds(int seconds);

They can either be invoked within your controller prior to content generation or specified as bean properties in Spring context.