spring boot + spring cache + r

一. spring cache

对于缓存,可以使用的框架太多,如reids,caffeine,ehcache等等,各有各自的优势。如果我们要想使用缓存,就得与这些框架耦合,为了避免这种情况,spring cache就利用AOP,实现基于注解的缓存功能,并进行合理的抽象,使业务代码不用担心底层使用了什么缓存框架。

二. 编码

1. maven依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
xml复制代码<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>

2. application.yml配置文件

1
2
3
4
5
6
7
8
9
10
yaml复制代码spring:
redis:
lettuce:
pool:
max-active: 8 # 连接池最大连接数
max-idle: 8 # 连接池最大空闲连接数
min-idle: 0 # 连接池最小空闲连接数
max-wait: -1ms # 连接池最大阻塞等待时间,负值表示没有限制
host: localhost
port: 6379

3. CacheConfig配置类

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
java复制代码/**
* @Description: 缓存配置
* @Author: songrenwei
* @Date: 2020/12/11/00:00
*/
@Configuration
@EnableCaching
public class CacheConfig {

@Bean
public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
RedisSerializer<String> stringRedisSerializer = new StringRedisSerializer();
//default信息缓存配置
RedisCacheConfiguration default1h = RedisCacheConfiguration.defaultCacheConfig()
// 设置过期时间
.entryTtl(Duration.ofHours(1))
// String的方式序列化key
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(stringRedisSerializer))
// jackson的方式序列化value
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jsonSerializer()))
// 空值不缓存
.disableCachingNullValues()
// 设置缓存名称前缀
.prefixCacheNameWith("default_1h:");
RedisCacheConfiguration m30 = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofMinutes(30)).serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(stringRedisSerializer)).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jsonSerializer())).disableCachingNullValues().prefixCacheNameWith("srw_");
RedisCacheConfiguration d30 = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofDays(30)).serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(stringRedisSerializer)).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jsonSerializer())).disableCachingNullValues().prefixCacheNameWith("srw_");
RedisCacheConfiguration h24 = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofHours(24)).serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(stringRedisSerializer)).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jsonSerializer())).disableCachingNullValues().prefixCacheNameWith("srw_");
RedisCacheConfiguration s60 = RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(60)).serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(stringRedisSerializer)).serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jsonSerializer())).disableCachingNullValues().prefixCacheNameWith("srw_");

Map<String, RedisCacheConfiguration> redisCacheConfigurationMap = new LinkedHashMap<String, RedisCacheConfiguration>(8) {
private static final long serialVersionUID = 2474073019770319870L;
{
put("60s", s60);
put("30m", m30);
put("24h", h24);
put("30d", d30);
put("default", default1h);
}
};

return new RedisCacheManager(RedisCacheWriter.nonLockingRedisCacheWriter(connectionFactory), default1h, redisCacheConfigurationMap);
}

@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
RedisSerializer<Object> jackson2JsonRedisSerializer = jsonSerializer();
StringRedisSerializer 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;
}

private RedisSerializer<Object> jsonSerializer() {
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);


// 解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance , ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
jackson2JsonRedisSerializer.setObjectMapper(om);
return jackson2JsonRedisSerializer;
}

}

4. 测试

4.1 controller

1
2
3
4
5
6
7
8
9
10
11
12
13
java复制代码@Slf4j
@RestController
@RequestMapping("/user")
@RequiredArgsConstructor
public class UserController {

private final UserService userService;

@GetMapping("/query/{id}")
public JsonResult<?> query(@PathVariable("id") Long id) {
return JsonResult.successResponse(userService.query(id));
}
}

4.2 service

1
2
3
4
5
6
7
8
9
10
11
12
13
java复制代码@Slf4j
@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

private final UserMapper userMapper;

@Cacheable(value = "30m", key = "#id", unless = "#result == null")
@Override
public User query(Long id) {
return userMapper.selectById(id);
}
}

4.3 测试结果

调用前先刷新下redis, 如下没有对应的key
在这里插入图片描述
postman调用接口
在这里插入图片描述
成功响应,查看日志
在这里插入图片描述
刷新redis
在这里插入图片描述
redis中已经存储了key, 以及缓存有效期
再调下接口,查看日志,未显示日志,说明已经走了redis。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%