Springboot 2.x CaffeineとRedisとカスタムキャッシュ時間の同時使用


一.ローカルキャッシュのカスタム構成の実装


1.@コンフィギュレーションクラスでは、カスタムbeanによるローカルキャッシュの柔軟な構成
`@Data public static class LocalCacheSpec {
private Integer timeout;  

private Integer max = 500; }//この変数名はプロファイルに対応するprivate Map localCacheSpecs;
2.ローカルキャッシュCacheManagerの構成
`@Beanpublic CacheManager caffeineCacheManager(Ticker ticker) {
SimpleCacheManager manager = new SimpleCacheManager();  

if (localCacheSpecs != null) {
    List caches = localCacheSpecs.entrySet().stream()  
                    .map(entry -> buildCache(entry.getKey(), entry.getValue(), ticker))  
                    .collect(Collectors.toList());  

manager.setCaches(caches); }
return manager;  

}`
3.アプリケーションの構成yml
`caching: local-cache-specs: test_user_map:
 max: 15  
 timeout: 10  

teststudent_map:
 max: 100  
 timeout: 20`

4.コードにvalueを作成する
`@Override@Cacheable(value="test_user_map",,key="'user:'+#id")public User getUser(Integer id){//データベースクエリユーザUser user=xx reture user;}`
ここで@Cacheable注記のvalue値とプロファイルは対応しています

二、Redisキャッシュの期限切れのカスタマイズを実現する


1.RedisCacheManagerの追加
`...//マッピングプロファイルの構成、異なるキャッシュ、異なる有効期限、変数名はプロファイルでprivate Map redisCacheSpecsを使用する必要があります.
@Bean public CacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()  
        .entryTtl(Duration.ofHours(4))  
        .prefixKeysWith("test:")//      
        .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));  

//異なるキャッシュ、異なる有効期限Map redisCacheConfigMap=new HashMap<>(redisCacheSpecs.size()for (Map.Entry entry : redisCacheSpecs.entrySet()) {
    redisCacheConfigMap.put(entry.getKey(), redisCacheConfiguration.entryTtl(Duration.ofSeconds(entry.getValue())));  

}
return RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))  
        .initialCacheNames(redisCacheSpecs.keySet())//       
        .withInitialCacheConfigurations(redisCacheConfigMap)  //     
        .cacheDefaults(redisCacheConfiguration).build();  

}`
2.すでに2つのCacheManagerがあるので、@PrimaryでデフォルトのCacheManagerを作成する必要があります.
3.application.ymlプロファイルはcachingで追加されます.
`redis-cache-specs: schoole_detail: 30 city_detail: 30`
4.コードでvalueとcacheManagerを作成する
`@Override @Cacheable(value = "school_detail",cacheManager = "redisCacheManager",key = "'school:'+#id") public School getSubVenueDetail(Long subVenueId) { ... return school;}`
以上でローカルとredisキャッシュ構成を実現し、同時に使用したり、期限切れを別々に構成したりすることができます.
アプリケーション全体の構成:`caching:local-cache-specs:test_user_map:
 max: 15  
 timeout: 10  

teststudent_map:
 max: 100  
 timeout: 20

redis-cache-specs: schoole_detail: 30 city_detail: 30`
Cofig構成クラス:`@ConfigurationProperties(prefix="caching")@Configuration@Slf 4 j@Data public class CacheConfig{
@Data public static class LocalCacheSpec {
private Integer timeout;  
private Integer max = 500;  

}//この変数名はプロファイルに対応するprivate Map localCacheSpecsです.private Map redisCacheSpecs;
@Beanpublic CacheManager caffeineCacheManager(Ticker ticker) {
SimpleCacheManager manager = new SimpleCacheManager();  

if (localCacheSpecs != null) {
    List caches = localCacheSpecs.entrySet().stream()  
                    .map(entry -> buildCache(entry.getKey(), entry.getValue(), ticker))  
                    .collect(Collectors.toList());  

manager.setCaches(caches); }
return manager;  

}
private CaffeineCache buildCache(String name, LocalCacheSpec cacheSpec, Ticker ticker) {
log.info("Cache {} specified timeout of {} min, max of {}", name, cacheSpec.getTimeout(), cacheSpec.getMax());  

final Caffeine caffeineBuilder
        = Caffeine.newBuilder()  
        .expireAfterWrite(cacheSpec.getTimeout(), TimeUnit.SECONDS)  
        .maximumSize(cacheSpec.getMax())  
        .ticker(ticker);  

return new CaffeineCache(name, caffeineBuilder.build()); }
@Bean public CacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()  
        .entryTtl(Duration.ofHours(4))  
        .prefixKeysWith("test:")//      
        .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));  

//異なるキャッシュ、異なる有効期限Map redisCacheConfigMap=new HashMap<>(redisCacheSpecs.size()for (Map.Entry entry : redisCacheSpecs.entrySet()) {
    redisCacheConfigMap.put(entry.getKey(), redisCacheConfiguration.entryTtl(Duration.ofSeconds(entry.getValue())));  

}
return RedisCacheManager.builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory))  
        .initialCacheNames(redisCacheSpecs.keySet())//       
        .withInitialCacheConfigurations(redisCacheConfigMap)  //     
        .cacheDefaults(redisCacheConfiguration).build();  

}
@Bean public Ticker ticker() {
return Ticker.systemTicker();  

}
}`