Improve cache auto-configuration for Redis
Expose key prefix, TTL and null value settings for spring-data-redis' RedisCacheConfiguration in Spring .properties/yml configuration files. Example: spring.cache.redis.ttl=PT15M spring.cache.redis.keyPrefix=foo spring.cache.redis.useKeyPrefix=false spring.cache.redis.cacheNullValues=false See gh-10795
This commit is contained in:
parent
25ddd4713a
commit
a4ed406ee8
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package org.springframework.boot.autoconfigure.cache;
|
package org.springframework.boot.autoconfigure.cache;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
@ -29,6 +30,7 @@ import org.springframework.util.Assert;
|
||||||
*
|
*
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
* @author Eddú Meléndez
|
* @author Eddú Meléndez
|
||||||
|
* @author Ryon Day
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@ConfigurationProperties(prefix = "spring.cache")
|
@ConfigurationProperties(prefix = "spring.cache")
|
||||||
|
@ -55,6 +57,8 @@ public class CacheProperties {
|
||||||
|
|
||||||
private final JCache jcache = new JCache();
|
private final JCache jcache = new JCache();
|
||||||
|
|
||||||
|
private final Redis redis = new Redis();
|
||||||
|
|
||||||
public CacheType getType() {
|
public CacheType getType() {
|
||||||
return this.type;
|
return this.type;
|
||||||
}
|
}
|
||||||
|
@ -91,6 +95,10 @@ public class CacheProperties {
|
||||||
return this.jcache;
|
return this.jcache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Redis getRedis() {
|
||||||
|
return this.redis;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve the config location if set.
|
* Resolve the config location if set.
|
||||||
* @param config the config resource
|
* @param config the config resource
|
||||||
|
@ -233,4 +241,69 @@ public class CacheProperties {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Redis-specific cache properties. Properties set will be used as the defaults for
|
||||||
|
* all Redis caches.
|
||||||
|
*/
|
||||||
|
public static class Redis {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the TTL (ultimately converted to seconds) for keys written to Redis.
|
||||||
|
* By default, entries do not expire, and a value of {@link Duration#ZERO} disables the TTL.
|
||||||
|
*/
|
||||||
|
private Duration ttl = Duration.ZERO;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to allow caching of {@literal null} values.
|
||||||
|
*/
|
||||||
|
private boolean cacheNullValues = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies an override for the default Redis key prefix. A value of {@literal null} results
|
||||||
|
* in usage of the default key prefix.
|
||||||
|
*/
|
||||||
|
private String keyPrefix;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether to use the key prefix when writing to Redis.
|
||||||
|
*/
|
||||||
|
private boolean useKeyPrefix = true;
|
||||||
|
|
||||||
|
public Duration getTtl() {
|
||||||
|
return this.ttl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Redis setTtl(Duration ttl) {
|
||||||
|
this.ttl = ttl;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCacheNullValues() {
|
||||||
|
return this.cacheNullValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Redis setCacheNullValues(boolean cacheNullValues) {
|
||||||
|
this.cacheNullValues = cacheNullValues;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKeyPrefix() {
|
||||||
|
return this.keyPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Redis setKeyPrefix(String keyPrefix) {
|
||||||
|
this.keyPrefix = keyPrefix;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUseKeyPrefix() {
|
||||||
|
return this.useKeyPrefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Redis setUseKeyPrefix(boolean useKeyPrefix) {
|
||||||
|
this.useKeyPrefix = useKeyPrefix;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import java.util.LinkedHashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
|
||||||
|
import org.springframework.boot.autoconfigure.cache.CacheProperties.Redis;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||||
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
|
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
|
||||||
|
@ -36,6 +37,7 @@ import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||||
*
|
*
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
* @author Mark Paluch
|
* @author Mark Paluch
|
||||||
|
* @author Ryon Day
|
||||||
* @since 1.3.0
|
* @since 1.3.0
|
||||||
*/
|
*/
|
||||||
@Configuration
|
@Configuration
|
||||||
|
@ -58,7 +60,7 @@ class RedisCacheConfiguration {
|
||||||
@Bean
|
@Bean
|
||||||
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
|
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
|
||||||
RedisCacheManagerBuilder builder = RedisCacheManager
|
RedisCacheManagerBuilder builder = RedisCacheManager
|
||||||
.builder(redisConnectionFactory);
|
.builder(redisConnectionFactory).cacheDefaults(getConfiguration());
|
||||||
List<String> cacheNames = this.cacheProperties.getCacheNames();
|
List<String> cacheNames = this.cacheProperties.getCacheNames();
|
||||||
if (!cacheNames.isEmpty()) {
|
if (!cacheNames.isEmpty()) {
|
||||||
builder.initialCacheNames(new LinkedHashSet<>(cacheNames));
|
builder.initialCacheNames(new LinkedHashSet<>(cacheNames));
|
||||||
|
@ -66,4 +68,26 @@ class RedisCacheConfiguration {
|
||||||
return this.customizerInvoker.customize(builder.build());
|
return this.customizerInvoker.customize(builder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private org.springframework.data.redis.cache.RedisCacheConfiguration getConfiguration() {
|
||||||
|
|
||||||
|
Redis redisProperties = this.cacheProperties.getRedis();
|
||||||
|
|
||||||
|
org.springframework.data.redis.cache.RedisCacheConfiguration config = org.springframework.data.redis.cache.RedisCacheConfiguration
|
||||||
|
.defaultCacheConfig().entryTtl(redisProperties.getTtl());
|
||||||
|
|
||||||
|
if (redisProperties.getKeyPrefix() != null) {
|
||||||
|
config = config.prefixKeysWith(redisProperties.getKeyPrefix());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!redisProperties.isCacheNullValues()) {
|
||||||
|
config = config.disableCachingNullValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!redisProperties.isUseKeyPrefix()) {
|
||||||
|
config = config.disableKeyPrefix();
|
||||||
|
}
|
||||||
|
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,7 @@ import static org.mockito.Mockito.verify;
|
||||||
* @author Stephane Nicoll
|
* @author Stephane Nicoll
|
||||||
* @author Eddú Meléndez
|
* @author Eddú Meléndez
|
||||||
* @author Mark Paluch
|
* @author Mark Paluch
|
||||||
|
* @author Ryon Day
|
||||||
*/
|
*/
|
||||||
@RunWith(ModifiedClassPathRunner.class)
|
@RunWith(ModifiedClassPathRunner.class)
|
||||||
@ClassPathExclusions("hazelcast-client-*.jar")
|
@ClassPathExclusions("hazelcast-client-*.jar")
|
||||||
|
@ -280,14 +281,25 @@ public class CacheAutoConfigurationTests {
|
||||||
@Test
|
@Test
|
||||||
public void redisCacheExplicit() {
|
public void redisCacheExplicit() {
|
||||||
this.contextRunner.withUserConfiguration(RedisCacheConfiguration.class)
|
this.contextRunner.withUserConfiguration(RedisCacheConfiguration.class)
|
||||||
.withPropertyValues("spring.cache.type=redis").run((context) -> {
|
.withPropertyValues("spring.cache.type=redis",
|
||||||
|
"spring.cache.redis.ttl=PT15M",
|
||||||
|
"spring.cache.redis.keyPrefix=foo",
|
||||||
|
"spring.cache.redis.useKeyPrefix=false",
|
||||||
|
"spring.cache.redis.cacheNullValues=false")
|
||||||
|
.run((context) -> {
|
||||||
RedisCacheManager cacheManager = getCacheManager(context,
|
RedisCacheManager cacheManager = getCacheManager(context,
|
||||||
RedisCacheManager.class);
|
RedisCacheManager.class);
|
||||||
assertThat(cacheManager.getCacheNames()).isEmpty();
|
assertThat(cacheManager.getCacheNames()).isEmpty();
|
||||||
assertThat(
|
|
||||||
((org.springframework.data.redis.cache.RedisCacheConfiguration) new DirectFieldAccessor(
|
org.springframework.data.redis.cache.RedisCacheConfiguration redisCacheConfiguration = (org.springframework.data.redis.cache.RedisCacheConfiguration) new DirectFieldAccessor(
|
||||||
cacheManager).getPropertyValue("defaultCacheConfig"))
|
cacheManager).getPropertyValue("defaultCacheConfig");
|
||||||
.usePrefix()).isTrue();
|
|
||||||
|
assertThat(redisCacheConfiguration.usePrefix()).isFalse();
|
||||||
|
assertThat(redisCacheConfiguration.getKeyPrefix()).contains("foo");
|
||||||
|
assertThat(redisCacheConfiguration.getTtl())
|
||||||
|
.isEqualTo(java.time.Duration.ofMinutes(15));
|
||||||
|
assertThat(redisCacheConfiguration.getAllowCacheNullValues())
|
||||||
|
.isFalse();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,6 +321,15 @@ public class CacheAutoConfigurationTests {
|
||||||
RedisCacheManager cacheManager = getCacheManager(context,
|
RedisCacheManager cacheManager = getCacheManager(context,
|
||||||
RedisCacheManager.class);
|
RedisCacheManager.class);
|
||||||
assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar");
|
assertThat(cacheManager.getCacheNames()).containsOnly("foo", "bar");
|
||||||
|
|
||||||
|
org.springframework.data.redis.cache.RedisCacheConfiguration redisCacheConfiguration = (org.springframework.data.redis.cache.RedisCacheConfiguration) new DirectFieldAccessor(
|
||||||
|
cacheManager).getPropertyValue("defaultCacheConfig");
|
||||||
|
assertThat(redisCacheConfiguration.usePrefix()).isTrue();
|
||||||
|
assertThat(redisCacheConfiguration.getKeyPrefix()).isEmpty();
|
||||||
|
assertThat(redisCacheConfiguration.getTtl())
|
||||||
|
.isEqualTo(java.time.Duration.ofMinutes(0));
|
||||||
|
assertThat(redisCacheConfiguration.getAllowCacheNullValues())
|
||||||
|
.isTrue();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue