Spring Boot2.x整合redis

看了好多篇文章,再根据自己的理解进行的配置。

一、Mevan相关配置

1.SpringBoot版本

1
2
3
4
5
6
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.0.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

2.引入spring-redis

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

二、application.yml配置

1
2
3
4
5
6
7
8
9
10
11
spring:
# 省略数据库等其它配置...
redis:
host: 127.0.0.1
port: 6379
database: 0
timeout: 1000s
cache:
redis:
time-to-live: 10000

三、redis配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package link.codedog.demo.configuration;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

@Configuration
@EnableCaching//启用缓存注解 用于开启@Cacheable、@CachePut、@CacheEvict
public class RedisConfig extends CachingConfigurerSupport {

public static final String REDIS_KEY_DATABASE = "messaging";

@Bean
public RedisTemplate<String,Object> redisTemplate(RedisConnectionFactory factory){
RedisTemplate<String,Object> template = new RedisTemplate<>();
// 配置连接工厂
template.setConnectionFactory(factory);
// 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
RedisSerializer jackson2JsonRedisSerializer = jsonSerializer();
RedisSerializer<String> stringRedisSerializer = new StringRedisSerializer();

// key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
// hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
// value序列化方式采用jackson
template.setValueSerializer(jackson2JsonRedisSerializer);
// hash的value序列化方式采用jackson
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();

return template;
}

@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(this.getRedisCacheConfigurationWithTtl(-1)) // 默认策略,未配置的 key 会使用这个
.withInitialCacheConfigurations(this.getRedisCacheConfigurationMap()) // 指定 key 策略
.build();
return cacheManager;
}


@Bean
public KeyGenerator simpleKeyGenerator() {
return (o, method, objects) -> {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(o.getClass().getSimpleName());
stringBuilder.append(".");
stringBuilder.append(method.getName());
stringBuilder.append("[");
for (Object obj : objects) {
stringBuilder.append(obj.toString());
}
stringBuilder.append("]");

return stringBuilder.toString();
};
}

/**
* 解决默认@Cacheable注解没有过期时间的问题
* @return
*/
private Map<String, RedisCacheConfiguration> getRedisCacheConfigurationMap() {
Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new HashMap<>();
redisCacheConfigurationMap.put(REDIS_KEY_DATABASE.concat(":ClueList"), this.getRedisCacheConfigurationWithTtl(3000));

return redisCacheConfigurationMap;
}

private RedisCacheConfiguration getRedisCacheConfigurationWithTtl(Integer seconds) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();

// 配置序列化(解决乱码的问题)
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(seconds))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jsonSerializer()))
.disableCachingNullValues();

return config;
}

private RedisSerializer jsonSerializer(){
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<Object>(Object.class);
//解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);

return jackson2JsonRedisSerializer;
}
}

四、使用

1
2
3
4
5
@Cacheable(value = "messaging:ClueList",keyGenerator = "simpleKeyGenerator",unless = "#result==null")
public List<Clue> getList(){
List<Clue> all = clueRepository.findAll();
return all;
}

要指定 key 的过期时间,只要在getRedisCacheConfigurationMap方法中添加就可以。
然后只需要 @Cacheable 就可以把数据存入redis

1
2
@Cacheable(value = "messaging:ClueList",keyGenerator = "simpleKeyGenerator",unless = "#result==null") // 3000秒
@Cacheable(value = "这里随便写个字符串", keyGenerator = "simpleKeyGenerator") // 不过期,未指定的key,使用默认策略