In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-22 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/01 Report--
This article mainly introduces how to configure multiple TTL caches in Spring Boot, which has a certain reference value, and interested friends can refer to it. I hope you will gain a lot after reading this article.
1. Case study
Let's start with the definition of the problem. Our imaginary application needs to cache two different REST endpoints, but one of them should expire more frequently than the other. Consider the following appearance implementation:
@ Serviceclass ForeignEndpointGateway {private RestTemplate restTemplate; ForeignEndpointGateway (RestTemplate restTemplate) {this.restTemplate = restTemplate;} @ Cacheable ("messages") public Message findMessage (long id) {String url = "http://somedomain.com/messages/" + id; return restTemplate.getForObject (url, Message.class) } @ Cacheable ("notifications") public Notification findNotification (long id) {String url = "http://somedomain.com/notifications/" + id; return restTemplate.getForObject (url, Notification.class);}}
The caching mechanism of the @ Cacheable annotation markup method Spring. It is worth mentioning that the caching method must be public. Each annotation specifies the name of the corresponding cache that should be used for a particular method.
The cache instance is just a simple key container. In our example, the key is created based on the input parameters, and the value is the result of the method, but it doesn't have to be that simple. The cache abstraction provided by Spring allows for more, but this is the subject of another article. If you are interested in details, I recommend you refer to the documentation. Let's stick to our main goal, which is to define different TTL values for the two declared caches.
two。 Common cache settings
Placing the @ Cacheable annotation on a method is not the only thing you need to run cache mechanization in your application. Depending on the provider selected, there may be several additional steps.
2.1. Turn on Spring caching
No matter which provider you choose, the starting point of the setting is always to add the @ EnableCaching annotation to one of your configuration classes, usually the main application class. This registers all required components in your Spring context.
@ SpringBootApplication@EnableCachingpublic class TtlCacheApplication {/ / content omitted for clarity} 2.2. Required dependencies
In regular Spring applications that use @ EnableCaching annotations, developers are required to provide bean of type CacheManager. Fortunately, the Spring Boot cache initiator provides a default manager and creates an appropriate cache provider based on the dependencies available on the classpath, in our case the Caffeine library.
Org.springframework.boot spring-boot-starter-cache com.github.ben-manes.caffeine caffeine2.3. Basic configuration
Most of the cache providers supported by Spring Boot can be adjusted using dedicated application properties. To set up TTL for the two caches required by the demo application, we can use the following values:
Spring.cache.cache-names=messages,notificationsspring.cache.caffeine.spec=maximumSize=100,expireAfterAccess=1800s
In a very simple way, we set the cached TTL to 30 minutes and set their capacity to 100. However, the main problem with this configuration is that all caches use the same settings. It is not possible to set a different specification for each cache. They all need to share a global. If you don't mind such restrictions, you can make basic settings. Otherwise, you should move on to the next section.
3. Differentiated caching
Spring Boot handles popular configurations effectively, but our scenario does not belong to this lucky group. In order to customize the cache according to our needs, we need to go beyond the predefined bean and write some custom initialization code.
3.1. Custom cache manager
There is no need to disable the default configuration provided by Spring Boot, because we can only override one necessary object. By defining a bean named cacheManager, we replaced the bean provided by Spring Boot. Let's create two caches. The first is called a message, and its expiration time is equal to 30 minutes. Another value called notification is stored for 60 minutes. When you create a custom cache manager, the settings in application.properties (described earlier in the basic example) are no longer used and can be safely deleted.
Beanpublic CacheManager cacheManager (Ticker ticker) {CaffeineCache messageCache = buildCache ("messages", ticker,30); CaffeineCache notificationCache = buildCache ("notifications", ticker,60); SimpleCacheManager manager = new SimpleCacheManager (); manager.setCaches (Arrays.asList (messageCache, notificationCache)); return manager } private CaffeineCache buildCache (String name, Ticker ticker,int minutesToExpire) {return new CaffeineCache (name, Caffeine.newBuilder (). NormalreAfterWrite (minutesToExpire, TimeUnit.MINUTES) .maximumSize (100) .ticker (ticker) .build ();} @ Beanpublic Ticker ticker () {return Ticker.systemTicker ();}
The Caffeine library comes with a convenient cache builder. In our demonstration, we only focus on different TTL values, but we can also customize other options as needed (such as capacity or useful expiration time after access).
In the above example, we also created ticker bean, which is shared by our cache. The automatic receiver is responsible for tracking the passage of time. In fact, it is not mandatory to pass an instance of type Ticker to the cache builder, and if it is not provided, Caffeine creates one. However, if we want to write tests for our solution, a separate bean will be easier to stub.
3.2. TTL cache test
The first thing we need in integration testing is a configuration class with fake code that allows you to simulate the passage of time. The Caffeine library itself does not provide such code, but the document mentions guava-testlib, which we need to declare as a dependency of our project.
Com.google.guava guava-testlib 20.0 test
If there is an internal static configuration class in the test class, the @ SpringBootTest annotation added in SpringBoot 1.4.0 automatically detects and leverages the internal static configuration class. By importing the main configuration class, we retained the original project settings and only replaced the stock symbol instance with a fake one.
@ RunWith (SpringRunner.class) @ SpringBootTestpublic class MessageRepositoryTest {@ Configuration @ Import (TtlCacheApplication.class) public static class TestConfig {static FakeTicker fakeTicker = new FakeTicker (); @ Bean public Ticker ticker () {return fakeTicker::read;}
We will use monitoring on the RestTemplate instance used by the cache gateway class to observe the number of possible calls to the real REST endpoint. The monitor should return some stub values to prevent the actual call from happening.
Private static final long MESSAGE_ID = 1private static final long NOTIFICATION_ID = 2; @ SpyBeanprivate RestTemplate restTemplate;@Autowiredprivate ForeignEndpointGateway gateway; @ Beforepublic void setUp () throws Exception {Message message = stubMessage (MESSAGE_ID); Notification notification = stubNotification (NOTIFICATION_ID); doReturn (message) .when (restTemplate) .getForObject (anyString (), eq (Message.class)) DoReturn (notification). When (restTemplate) .getForObject (anyString (), eq (Notification.class));}
Finally, we can write a test with our Happy path scenario to confirm that the TTL configuration meets our expectations.
@ Testpublic void shouldUseCachesWithDifferentTTL () throws Exception {/ / 0 minutes foreignEndpointGateway.findMessage (MESSAGE_ID); foreignEndpointGateway.findNotification (NOTIFICATION_ID); verify (restTemplate, times (1)) .getForObject (anyString (), eq (Message.class)); verify (restTemplate, times (1)) .getForObject (anyString (), eq (Notification.class)); / / after 5 minutes TestConfig.fakeTicker.advance (5, TimeUnit.MINUTES); foreignEndpointGateway.findMessage (MESSAGE_ID) Verify (restTemplate, times (1)) .getForObject (anyString (), eq (Message.class)); / / after 35 minutes TestConfig.fakeTicker.advance (30, TimeUnit.MINUTES); foreignEndpointGateway.findMessage (MESSAGE_ID); foreignEndpointGateway.findNotification (NOTIFICATION_ID); verify (restTemplate, times (2)) .getForObject (anyString (), eq (Message.class)); verify (restTemplate, times (1)) .getForObject (anyString (), eq (Notification.class)) / / after 65 minutes TestConfig.fakeTicker.advance (30, TimeUnit.MINUTES); foreignEndpointGateway.findNotification (NOTIFICATION_ID); verify (restTemplate, times (2)) .getForObject (anyString (), eq (Notification.class));}
Initially, both Message and Notification objects are fetched from the endpoint and placed in the cache. After 5 minutes, the Message object will be called again. Because the message cache TTL is configured for 30 minutes, we expect to get this value from the cache and will not invoke the endpoint. After another 30 minutes, we expect the cached message to have expired, and we confirm this with another call to the endpoint. However, the notification cache is configured to retain the value for 60 minutes. By trying to get the notification again, we confirm that the other cache is still valid. Finally, the automatic receiver moves forward for another 30 minutes, for a total of 65 minutes from the start of the test. We verify that the notification has also expired and deleted from the cache.
3. TTL with other cache providers
As mentioned earlier, the main disadvantage of Caffeine is that it cannot distinguish between all caches. The specifications in spring.cache.caffeine.spec apply globally. We hope to simplify the setup of multiple caches in future releases, but for now we need to stick to manual configuration.
Fortunately for other cache providers, the situation is much easier. EhCache, Hazelcast, and Infinitspan use dedicated XML configuration files, where each cache can be configured separately.
Thank you for reading this article carefully. I hope the article "how to configure multiple TTL caches in Spring Boot" shared by the editor will be helpful to you. At the same time, I also hope you will support us and pay attention to the industry information channel. More related knowledge is waiting for you to learn!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.