前面的SpringCache缓存说过在没有引入其他缓存中间件时,默认使用的是ConcurrentMapCacheManager=ConcurrentMapCache,是将数据保存在ConcurrentMap<Object, Object>
中。
在实际开发中,我们一般都会使用redis
、memcached
、ehcache
来作为缓存中间件。
整合Redis
Redis
是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。
当我们引入Reids
的starter
依赖的时候,使用RedisCacheManager
。RedisCacheManager
会帮我们创建RedisCache
来作为缓存组件,RedisCache通过操作redis缓存数据。
1、引入Redis的starter的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 连接池 - luttuce依赖该连接池 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.4.2</version>
</dependency>
2、配置yml
配置文件
spring:
redis:
host: 127.0.0.1 # Redis连接地址
port: 6379 # redis连接端口
lettuce: # 使用lettuce客户端
pool:
max-active: 8 # 连接池最大连接数(负值表示没有限制)
max-idle: 8 # 连接池的最大空闲连接
min-idle: 0 # 连接池的最小空闲连接
max-wait: -1ms # 连接池最大阻塞等待时间(赋值表示没有限制)
database: 0 # 默认使用索引为0的数据库
timeout: 5000ms # 连接超时时间
3、序列化配置
Reids默认使用的是JDK的序列化机制,我们通过RedisDesktopManager
去查看存储的数据,是无法用肉眼看出存的是什么的。
比如说我们要存一个对象进去,并且想直接肉眼看到是一个怎么样的数据,可以通过修改配置,让其以Json
的格式去保存。
创建一个配置类继承CachingConfigurerSupport
@Configuration
public class RedisConfiguration extends CachingConfigurerSupport {
/**
* 采用RedisCacheManager作为缓存管理器
* @param connectionFactory Redis连接工厂 - 配置的是Luttuce客户端,则这里就是LuttuceFactory
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory connectionFactory){
RedisCacheManager redisCacheManager = RedisCacheManager.create(connectionFactory);
return redisCacheManager;
}
/**
* RedisTemplate模板
* @param factory Redis连接工厂
*/
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory){
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 使用Jackson进行序列化配置
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
// 如果enableDefaultTyping过期(SpringBoot后续版本过期了),则使用下面这个代替
om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY);
jackson2JsonRedisSerializer.setObjectMapper(om);
// String序列化
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;
}
}
4、测试一下
// 注入RedisTemplate
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
// 向Redis中存数据
@GetMapping("/test")
public String test(){
BoundHashOperations boundHashOps = redisTemplate.boundHashOps("User");
List list = new ArrayList();
User user1 = new User("柳成荫", "男", 22);
list.add(user1);
list.add(user1);
boundHashOps.put("3",list);
return "ok";
}
// 向Redis取数据
@GetMapping("/test1")
public List test1(){
BoundHashOperations boundHashOps = redisTemplate.boundHashOps("User");
List<User> users = (List<User>) boundHashOps.get("3");
return users;
}
可以看到确实存入的是JSON序列化的结果
取出来也是没有问题的
RedisUtils
自定义的RedisUtils用着比RidsTemplate方便很多,所以一般都会自己封装一个工具类。
@Component
public class RedisUtils {
// 注入自己的RedisTemplate
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// ================================== 共用部分 ====================================
/**
* 指定缓存失效时间
* @param key 键
* @param time 时间(秒)
*/
public boolean expire(String key, long time){