SpringCache基本配置类
# 起步依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
1
2
3
4
2
3
4
1
2
3
4
2
3
4
# SpringCacheConfig
同时配置带过期时间的CacheManager
自定义Json
序列化方式存储
import cn.hutool.core.util.RandomUtil;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.cache.CacheManager;
import org.springframework.cache.support.NoOpCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
/**
* spring cache配置
*/
@Configuration
public class SpringCacheConfig {
@Value("${cache.enabled}")
private Boolean cacheEnabled;
/**
* 随机数上界-1天时间内随机数
*/
private static final long CACHE_RANDOM_LIMIT = 24 * 60 * 60 * 1000L;
/**
* 获取缓存时间
* 缓存时间=sourceCacheTtl+random limit
*
* @param sourceCacheTtl sourceCacheTtl
* @param limit limit
* @return long
*/
private long cacheTtlWithRandom(long sourceCacheTtl, long limit) {
long random = RandomUtil.randomLong(limit);
return sourceCacheTtl + random;
}
/**
* 同时随机过期时间解决缓存雪崩问题
*
* @return CacheManager
*/
@Bean("testCache")
public CacheManager cacheManager1Day(RedisConnectionFactory connectionFactory) {
if (!cacheEnabled) {
// 禁用缓存,不会存储
return new NoOpCacheManager();
}
// 3天过期时间,转换成毫秒
long threeDaysInMillis = 3 * 24 * 60 * 60 * 1000L;
// 过期时间和最大空闲时间都设为3天+随机时间
long trueTtl = cacheTtlWithRandom(threeDaysInMillis, CACHE_RANDOM_LIMIT);
RedisCacheConfiguration config = instanceConfig(trueTtl);
return RedisCacheManager.builder(connectionFactory)
.cacheDefaults(config)
.transactionAware()
.build();
}
/**
* 初始化config
*
* @param ttl 超时时间
* @return RedisCacheConfiguration
*/
private RedisCacheConfiguration instanceConfig(Long ttl) {
// value存储为JSON格式
// 使用Jackson2JsonRedisSerialize 替换默认序列化
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
// 指定objectMapper带输入类型的序列化,如果不指定redis中则存储纯json,序列化返回后解析默认为LinkedHashMap
// 需要自己转换类型,指定序列化类型后无需再进行转化
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.enableDefaultTyping(LaissezFaireSubTypeValidator.instance,
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);
// 处理LocalDateTime
objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
objectMapper.registerModule(new JavaTimeModule());
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
return RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(ttl))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer));
}
}
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
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
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
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
带过期时间的CacheManager
使用方法如下
@Cacheable(cacheNames = "TestName",
key = "'123456'",
cacheManager = "testCache",
sync = true)
1
2
3
4
2
3
4
1
2
3
4
2
3
4
其中存储到Redis
中的key
的规则为
- 当没有配置
key
时:key=cacheNames+::+SimpleKey []
,如TestName::SimpleKey []
- 当配置了
key
时:key=cacheNames+::+key
,如TestName::123456
编辑 (opens new window)
上次更新: 2024/05/20, 17:55:40
- 02
- Rpamis-security-原理解析12-13
- 03
- Rpamis-security-技术背景11-29