Recently, I had to cache some values during processing HTTP request in Spring application. Spring does not offer out of the box solution for this, so I had to write my own request cache.
In first step, we need to define an annotation, which will help us to mark methods which calls should be cached:
Next step is implement a cache manager:
As we see, cache manager is standard Spring component which is annotated with @RequestScope which means, that Spring IoC will create new instance of our manager for every HTTP request. We will use ConcurrentHashMap to cache our values (this map is thread safe - if you know that you will work with single thread, you should use HashMap - it’s not thread safe but faster).
Our cache manager has two methods - one to get value and second to put value in cache. The key of our map is InvocationTarget object which implementation is:
As we can see, it contains class, method and arguments of method call. It allows us to determine, if the method from same class was called with same arguments. As we use objects of this class as ConcurrentHashMap key, we need to remember to override hashCode and equals methods from Java Object class.
When we have these elements, we can implement aspect which will allow us to process value caching.
This aspect processes around method annotated with @RequestCache. It constructs InvocationTarget object and checks, if cache contains value for this key.
If cached result is present, then this cached value is returned. Otherwise target method is called and result is stored in our cache.
It’s time to test our implementation. Let’s create class which calls will be cached:
It should generate new random number every time when getRandomNumber method is called.
Let’s create controller which will use this class:
This controller calls RandomGenerator twice, so if our cache is working second call should return same value as with the first call.
Let’s start our application with command: mvn spring-boot:run
and then type in our browser:
http://localhost:8080/random
Now it’s time to check logs:
As we can see first call of RandomGenerator was successfully cached. Every thing works as expected!
Spring does not offer every kind of cache out of the box, but it’s powerful framework and we can simply implement our custom cache using Spring features.
You can find the source code in my Github repository how-to under a requestcache directory.
Hope you enjoy this post. If You have any questions or problems leave a comment or send email.