Cache HTTP Response in Spring MVC Rest Service

I have an MVC spring service that returns data in XML. I would like to cache this xml answer. How can i achieve this? Can this be done using mvc: interceptors?

+6
spring spring-mvc caching
source share
6 answers

You can do this work, but I think there are better solutions.

First, if you want to use Spring MVC hooks, you'll use the postHandle method to store something in your cache and preHandle to check the cache and possible workaround. The question is what do you store in cache. You will need to save the full answer. This means that you will need to easily get the full answer from your ModelAndView in postHandle. This may or may not be easy, depending on how you do it.

Most likely, you are better off using a different caching mechanism. I recommend caching at the web server level. This is especially true if you are looking for cache at the interceptor level, as it is right β€œnext to” the web server, and I see no benefit in reinventing the wheel. Apache has a cache module. So does nginx. The varnish is also very cool.

I should also mention that you should not cache until you decide what you need (prematurely optimize). This is a waste of time and effort. Secondly, when you determine that you have performance issues that need to be fixed (and caching is the right solution), you must cache the right data in the right place.

Now say that you have determined that you have performance problems, and some kind of caching is a good solution. The next thing to determine is what can be cached. If you return the same data for each URL, then caching on the web server (level Apache, nginx, Varnish, etc.) is the best choice.

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

+5
source

I could no longer disagree with the optimization part.

Web requests are inherently slow since you are downloading data from a remote location, perhaps several thousand miles away. Each call must have a full TCP connection for at least the packets themselves, possibly a connection and fin for each request, which is a three-packet synchronous exchange for the connection before you begin to transfer data.

The wait time from the coast to the US coast is about 50 ms on a good day, so each connection suffers a fine of 150 ms, which for most implementations is incurred for each request.

Client-side response caching completely eliminates this delay, and if the service has the correct headers for the response, it is trivial. If this does not happen, you will need to define a caching policy, which for the most part is not particularly complex. Most API calls are either real-time or not.

In my opinion, caching REST responses is a premature optimization, it is common sense.

+4
source

I use this and it works at amazing speed. Really easy to use spring + ehcache:

1) Controller:

@Cacheable("my.json") @RequestMapping("/rest/list.json") public ResponseEntity list(@RequestParam(value = "page", defaultValue = "0", required = false) int pageNum, @RequestParam(value = "search", required = false) String search) throws IOException { ... } 

2) In ehcache.xml something like this:

  <cache name="my.json" maxElementsInMemory="10000" eternal="true" overflowToDisk="false"/> 

3) Configure spring. I am using spring javaconf style:

 @Configuration @EnableCaching public class ApplicationConfiguration { @Bean public EhCacheManagerFactoryBean ehCacheManagerFactoryBean() throws MalformedURLException { EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean(); ehCacheManagerFactoryBean.setConfigLocation(new ClassPathResource("ehcache.xml")); return ehCacheManagerFactoryBean; } @Bean @Autowired public EhCacheCacheManager cacheManager(EhCacheManagerFactoryBean ehcache) { EhCacheCacheManager ehCacheCacheManager = new EhCacheCacheManager(); ehCacheCacheManager.setCacheManager(ehcache.getObject()); return ehCacheCacheManager; } } 
+2
source

At the application level, I would use a regular Java cache as EHCache. EHCache integrates fairly easily with methods on Spring beans. You could annotate your service methods as @Cacheable , and that was done. Check it out on EHCache Spring Annotations .

At the HTTP level, Spring MVC provides a useful ETag filter . But I think it would be better if you could configure such caching at the server level more than at the application level.

0
source

Do not use spring cache, this is not what you need. You need to reduce the load on the server, not speed up the execution of the internal spring application.

Try caching strategies related to HTTP.

You can add one of the HTTP headers to your requests.

 #cache expires in 3600 seconds cache-control: private, max-age=3600 #hash of your content ETag: "e6811cdbcedf972c5e8105a89f637d39-gzip" # redirect caching to any HTTP header vary: User-Agent 

Detailed Caching Methods

Spring example

 @RequestMapping (value = "/resource/1.pdf", produces = "application/octet-stream") public ResponseEntity<InputStreamResource> getAttachement (@RequestParam (value = "id") Long fileId) { InputStreamResource isr = new InputStreamResource(javaInputStream); HttpHeaders headers = new HttpHeaders(); //other headers headers.setCacheControl("private, max-age=3600"); return new ResponseEntity<>(irs, headers, HttpStatus.OK); } 
0
source

As with Spring 3.1, you can use the @Cachable annotation. There is also support for conditional caching and some sibling annotations, such as @CachePut , @CacheEvict and @ Caching for finer control.

Spring currently supports two different cache managers , one supported by ConcurrentHashMap and one supported by Ehcache.

Finally, be sure to read the details on enable annotations.

-one
source

All Articles