转载

Springboot 2.x 同时使用Caffeine 和 Redis 及自定义缓存时间

一.实现本地缓存自定义配置

1.@Configuration配置类中,自定义bean实现本地缓存的灵活配置

`@Data

public static class LocalCacheSpec {

private Integer timeout;

private Integer max = 500;

}

//该变量名称会与配置文件中相对应

private Map<String, LocalCacheSpec> localCacheSpecs;`

2.配置本地缓存CacheManager

`@Bean

public CacheManager caffeineCacheManager(Ticker ticker) {

SimpleCacheManager manager = new SimpleCacheManager();

if (localCacheSpecs != null) {

List<CaffeineCache> caches = localCacheSpecs.entrySet().stream()  
                    .map(entry -> buildCache(entry.getKey(), entry.getValue(), ticker))  
                    .collect(Collectors.toList());

manager.setCaches(caches);

}

return manager;

}`

3.配置application.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 = xxxx

reture user;

}`

其中 @Cacheable注解的value值和配置文件中是对应起来的

二、实现Redis缓存过期时间自定义

1.添加RedisCacheManager

`

...

//映射配置文件中的配置,不同缓存,不同过期时间,变量名需要在配置文件中使用

private Map<String,Integer> redisCacheSpecs;

...

@Bean

public CacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {

RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()  
        .entryTtl(Duration.ofHours(4))  
        .prefixKeysWith("test:")//缓存前缀  
        .serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()));

//不同缓存,不同过期时间

Map<String, RedisCacheConfiguration> redisCacheConfigMap = new HashMap<>(redisCacheSpecs.size());

for (Map.Entry<String, Integer> 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.现在已经有两个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缓存配置,同时使用,也可以分别配置过期时间。

application整体配置:

`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

@Slf4j

@Data

public class CacheConfig {

@Data

public static class LocalCacheSpec {

private Integer timeout;  
private Integer max = 500;

}

//该变量名称会与配置文件中相对应

private Map<String, LocalCacheSpec> localCacheSpecs;

private Map<String,Integer> redisCacheSpecs;

@Bean

public CacheManager caffeineCacheManager(Ticker ticker) {

SimpleCacheManager manager = new SimpleCacheManager();

if (localCacheSpecs != null) {

List<CaffeineCache> 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<Object, Object> 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<String, RedisCacheConfiguration> redisCacheConfigMap = new HashMap<>(redisCacheSpecs.size());

for (Map.Entry<String, Integer> 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();

}

}`

原文  https://segmentfault.com/a/1190000021546433
正文到此结束
Loading...