How to Enable Http Response Caching in Spring Boot

How to enable HTTP response caching in Spring Boot

Turns out the no-cache HTTP headers are set by Spring Security. This is discussed in http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#headers.

The following disables the HTTP response header Pragma: no-cache, but doesn't otherwise solve the problem:

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;

@Configuration
@EnableWebMvcSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// Prevent the HTTP response header of "Pragma: no-cache".
http.headers().cacheControl().disable();
}
}

I ended up disabling Spring Security completely for public static resources as following (in the same class as above):

@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/static/public/**");
}

This requires configuring two resource handlers to get cache control headers right:

@Configuration
public class MvcConfigurer extends WebMvcConfigurerAdapter
implements EmbeddedServletContainerCustomizer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// Resources without Spring Security. No cache control response headers.
registry.addResourceHandler("/static/public/**")
.addResourceLocations("classpath:/static/public/");

// Resources controlled by Spring Security, which
// adds "Cache-Control: must-revalidate".
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/static/")
.setCachePeriod(3600*24);
}
}

See also Serving static web resources in Spring Boot & Spring Security application.

Enable Http Cache in Spring Boot

Ok, I noticed that it was working with IE, but not with Chrome. The problem with Chrome is that it sets Cache-control: max-age=0 on the request's header if you're refrehsing the page. This obviously prevents the data from being cached. I then created a simple html using a hyperlink to my application and refresehing it via this link. Thus, the cache worked as expected.

Cache HTTP Response in Spring MVC Rest service

You could make this work, but I think there are better solutions.

First, if you want to use Spring MVC interceptors, you'll use the postHandle method to store something in your cache and the preHandle to check the cache and possible circumvent processing. The question is, what do you store in the cache. You would need to store the complete response. This means that you would have to easily get the full response from your ModelAndView in postHandle. This may or may not be easy, depending on how you're doing things.

You're most likely better off using a different caching mechanism all together. I recommend caching at the web server level. This is especially true if you're looking to cache in the interceptor level as that is right "next" to the web server and I don't see any benefit in re-inventing the wheel there. Apache has a cache module. So does nginx. Varnish is pretty awesome too.

I should also mention that you should not cache until you've determined that you need to (don't prematurely optimize). This is a waste of your time and effort. Secondly, when you've determined that you do have performance issues that need to be fixed (and caching is the correct solution), you should cache the right data in the right place.

Now, say you've determined that you do have a performance problem and some sort of caching is a good solution. The next thing to determine is what can be cached. If, for every URL, you return the same data, then caching at the web server (Apache, nginx, Varnish, etc.) level will be your best bet.

Often, you will have cases where two clients will hit the same URL and get different data. This is most easily seen on a site like Facebook. I see different data when I'm logged in than my friend sees. In this case, you will not be able to cache at the web server level. You will need to cache inside your application. Usually this means caching at the database level.

How to enable browser caching in spring boot

Turns out it is fairly easy to resolve.

The directory structure is classpath:/static/assets. To have no cache-control header added to the responds, add this class:

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/assets/**").addResourceLocations("classpath:/static/assets/").setCacheControl(CacheControl.empty());
}
}

It still baffled me that "no-store" is the default with spring-boot..

How to add Cache-Control header to static resource in Spring Boot?

As per the documentation, of ResourceHandlerRegistry. It is pretty easy. (I have no code related to it right now.)

In the place where you configure your static resources just add addResourceHandler method, It will return ResourceHandlerRegistration object.

There you can use setCacheControl method. What you have to do is configure and set a CacheControl obejct.

This is since spring 4.2, else you will have to do it like below.

@Configuration
@EnableWebMvc
@ComponentScan("my.packages.here")
public class WebConfig extends WebMvcConfigurerAdapter {

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

}


Related Topics



Leave a reply



Submit