Spring Data Redis encapsulates various operations on the Redis client for us, simplifying the use.
- When Redis operates as a database or message queue, we typically use RedisTemplate to operate
- When Redis is used as a Cache, we can use it as an implementation of Spring Cache, directly through annotations
About the use of RedisTemplate reference: blog.didispace.com/springbootr…
The following summary uses Redis as the cache
Introduction of depend on
Since version 1.4, the spring-boot-starter-redis dependency has been renamed.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>1.5.2. RELEASE</version>
</dependency>
Copy the code
The configuration file
spring:
redis:
host: 127.0. 01.
port: 6379
timeout: 0
database: 0
pool:
max-active: 8
max-wait: - 1
max-idle: 8
min-idle: 0
Copy the code
SpringBoot will then automatically configure Redis, inject the relevant beans, and we can use @Cacheconfig, @Cacheable, @CachePut, @cacheevict.
Problems with Cache annotations
In the cache object collection, the cache is stored as a key-value. When no cached key is specified, SpringBoot uses SimpleKeyGenerator to generate the key.
public class SimpleKeyGenerator implements KeyGenerator {
@Override
public Object generate(Object target, Method method, Object... params) {
return generateKey(params);
}
/** * Generate a key based on the specified parameters. */
public static Object generateKey(Object... params) {
if (params.length == 0) {
return SimpleKey.EMPTY;
}
if (params.length == 1) {
Object param = params[0];
if(param ! =null && !param.getClass().isArray()) {
returnparam; }}return newSimpleKey(params); }}Copy the code
public SimpleKey(Object... elements) {
Assert.notNull(elements, "Elements must not be null");
this.params = new Object[elements.length];
System.arraycopy(elements, 0.this.params, 0, elements.length);
this.hashCode = Arrays.deepHashCode(this.params);
}
Copy the code
Looking at the source code, you can see that it is a key generated using a combination of method parameters. There is a problem: if two methods have the same parameters but different execution logic, the second method will hit the cache of the first method. The workaround is to specify the key in the @cacheable annotation parameter, or to implement a KeyGenerator of your own and specify the KeyGenerator in the annotation. However, if there are many such cases, specifying key and KeyGenerator for each one can be troublesome.
Spring also provides a solution: Inherit CachingConfigurerSupport and rewrite keyGenerator()
Post the code below:
@EnableCaching
@Configuration
public class RedisCacheConfig extends CachingConfigurerSupport {
@Autowired
private JedisConnectionFactory jedisConnectionFactory;
@Bean
public RedisTemplate redisTemplate(a) {
StringRedisTemplate redisTemplate = new StringRedisTemplate(jedisConnectionFactory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
@Bean
public CacheManager cacheManager(a) {
String[] cacheNames = {"app_default"."users"."blogs"."goods"."configs"."info"};
RedisCacheManager redisCacheManager = new RedisCacheManager(redisTemplate(), Arrays.asList(cacheNames));
redisCacheManager.setDefaultExpiration(86400);
return redisCacheManager;
}
@Bean
public Cache cache(a) {
return cacheManager().getCache("app_default");
}
@Bean
@Override
public KeyGenerator keyGenerator(a) {
return (target, method, objects) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append("... "" + method.getName() + ":");
for (Object obj : objects) {
sb.append(obj.toString());
}
returnsb.toString(); }; }}Copy the code
In this case, the cache key is the package name + method name + parameter list, which makes it hard to conflict.