SpringBoot2.x使用Redis实现缓存入门
Redis简介
Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。
Redis安装
使用docker安装redis步骤
1.安装Linux虚拟机,可以先安装VMWare或VirtualBox,然后安装CentOS7,具体安装步骤各大博客都有详细说明这里不再赘述。
2.在linux虚拟机上安装docker
- 检查linux内核版本,必须是3.10及以上
[root@localhost ~]# uname -r
- 安装docker
[root@localhost ~]# yum install docker
- 启动docker
[root@localhost ~]# systemctl start docker
- 如果启动成功可以查看docker的版本
[root@localhost ~]# docker -v
- 设置开机启动docker
[root@localhost ~]# systemctl enable docker
- 停止docker
[root@localhost ~]# systemctl stop docker
- 获取更多docker镜像可以查看以下地址
3.使用docker安装redis
- 使用镜像加速拉取redis镜像
[root@localhost ~]# docker pull registry.docker-cn.com/library/redis
- 查看docker镜像列表
[root@localhost ~]# docker images
- 使用redis镜像运行容器
‐d:后台运行
‐p: 端口映射,将主机的端口映射到容器的一个端口 主机的端口:容器内部的端口
--name myredis为别名[root@localhost ~]# docker run -d -p 6379:6379 --name myredis registry.docker-cn.com/library/redis
- 查看运行中的容器
补充: docker ps -a 查看所有容器(包括已启动的和未启动的)
[root@localhost ~]# docker ps
- 查看linux防火墙状态
[root@localhost ~]# service firewalld status
- 关闭linux的防火墙
[root@localhost ~]# service firewalld stop
在pom文件中引入redis的starter,并添加Jedis的依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>2.1.1.RELEASE</version>
<!-- 1.5的版本默认采用的连接池技术是jedis 2.0以上版本默认连接池是lettuce, 在这里采用jedis,所以需要排除lettuce的jar -->
<exclusions>
<exclusion>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</exclusion>
<exclusion>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 添加jedis客户端 -->
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<!--springboot2.0集成redis所需common-pool2-->
<!-- 必须加上,jedis依赖此 -->
<!-- springboot 2.0 的操作手册有标注 地址是:https://docs.spring.io/spring-boot/docs/2.0.3.RELEASE/reference/htmlsingle/-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>RELEASE</version>
</dependency>
在application.properties文件中简单配置redis
#redis的主机地址填写虚拟机的IP
spring.redis.host=
#redis的端口默认是6379,也可以不配
spring.redis.port=6379
先来简单看一下SpringBoot操作Redis的自动配置
当我们引入了 spring-boot-starter-data-redis 时,RedisAutoConfiguration自动配置类就生效了,查看如下源码,可以看到它帮我们注入了RedisTemplate<Object, Object>和StringRedisTemplate两个组件来操作redis,其中RedisTemplate<Object, Object>的键值都是对象,StringRedisTemplate用来操作字符串的。
@Configuration
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean
@ConditionalOnMissingBean
public StringRedisTemplate stringRedisTemplate(
RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
StringRedisTemplate
- stringRedisTemplate.opsForValue() 操作String(字符串)
- stringRedisTemplate.opsForList() 操作List(列表)
- stringRedisTemplate.opsForSet() 操作Set(集合)
- stringRedisTemplate.opsForHash() 操作Hash(散列)
- stringRedisTemplate.opsForZSet() 操作ZSet(有序集合)
RedisTemplate
例如我们调用查询方法向数据库查询一条数据返回一个Student对象放到redis中,这里举例说明如何存储对象,Student实体类和Mapper类不做详细说明,大家自己可以创建自己的实体类进行测试,实体类要实现 Serializable 序列化接口。
//自动注入 RedisTemplate
@Autowired
RedisTemplate redisTemplate;
public void test(){
Student student = studentMapper.getStuById(1);
redisTemplate.opsForValue().set("stu01",student);
}
如果保存对象,我们可以查看RedisTemplate的源码,它会使用jdk序列化机制,序列化后的数据保存在redis中。
如果希望将数据序列化为json格式,改变默认的序列化规则,我们编写Redis的配置类将默认的序列化器改为json的序列化器,将我们自己写的RedisTemplate<Object, Student> 注入即可。
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<Object, Student> stuRedisTemplate(
RedisConnectionFactory redisConnectionFactory) {
//Student是要序列化的javabean
RedisTemplate<Object, Student> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer<Student> serializer = new Jackson2JsonRedisSerializer<>(Student.class);
template.setDefaultSerializer(serializer);
return template;
}
}
如何自定义CacheManager
CacheManager通过管理Cache缓存组件来给缓存中存取数据,我们引入了 spring-boot-starter-data-redis 那么Spring容器中保存的就是 RedisCacheManager,RedisCacheManager会创建RedisCache作为缓存组件,RedisCache操作redis缓存数据。
保存数据时,如果key和value都是Object,默认使用jdk的序列化机制保存数据,如果希望存取格式为json,我们可以自定义RedisCacheManager,这里以两个RedisCacheManager为例,实际应用中会创建多个RedisCacheManager,但是创建多个edisCacheManager时,必须使用 @Primary 指定默认的CacheManager,然后在Service类上指定该类使用的CacheManager即可,如@CacheConfig(cacheManager = "xxxCacheManager")。
@Configuration
public class MyRedisConfig {
//指定默认的CacheManager
@Primary
@Bean
public RedisCacheManager studentCacheManager(RedisConnectionFactory factory){
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Student.class);//传入自己的实体类
//处理查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置序列化
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;
}
@Bean
public RedisCacheManager schoolCacheManager(RedisConnectionFactory factory){
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(School.class);//传入自己的实体类
//处理查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置序列化
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;
}
}
最后,在主类上使用 @EnableCaching 开启基于注解的缓存,在要支持缓存的类或方法上添加 @Cacheable 注解即可快速体验缓存功能。