Redis是一个开源(BSD)的,内存中的数据结构存储系统,它可以作为数据库、缓存和消息中间件。详细命令使用可以参考官网http://www.redis.cn/commands.html
1. 整合RedisTemplate
1.1 引入redis启动器
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
1.2 配置redis
只需要配置redis的主机即可
spring.redis.host=localhost
1.3 注入RedisTemplate
当我们引入redis启动器的时候,这时候,RedisAutoConfiguration自动配置类就生效了,打开该类,可以看到,其给我们注入了两个Template,一个是RedisTemplate<Object, Object>,一个是StringRedisTemplate
源码如下:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package org.springframework.boot.autoconfigure.data.redis;
import java.net.UnknownHostException;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnClass({RedisOperations.class})
@EnableConfigurationProperties({RedisProperties.class})
@Import({LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class})
public class RedisAutoConfiguration {
public 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;
}
}
所以,我们可以在我们的程序中通过spring的依赖注入直接引入这两个Template
例如:
@SpringBootTest
class SpringBoot01CacheApplicationTests {
@Autowired
private RedisTemplate<String,String> template;
@Test
public void testSetAdd() {
template.boundSetOps("myRedis").add("張三","李四");
}
}
在redis中有五大数据类型,分别是:string(字符串)、list(列表)、Set(集合)、Hash(散列)、ZSet(有序集合)
在RedisTemplate给我们提供了各种API可以分别操作这几种对象,以StringRedisTemplate为例
1.3.1 操作String——opsForValue
通过stringRedisTemplate.opsForValue()来进行string类型的操作。
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
public void optString(){
stringRedisTemplate.opsForValue().append("stringTemplate","temp1");
}
查看redis数据库,如图:
1.3.2 操作集合列表——opsForList
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
public void optList(){
stringRedisTemplate.opsForList().leftPush("optList","Mary");
}
1.3.3 操作Set集合——opsForSet
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
public void optSet(){
stringRedisTemplate.opsForSet().add("optSet","李四");
}
1.3.4 操作Hash散列——opsForHash
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
public void optHash(){
stringRedisTemplate.opsForHash().put("optHash","name","张三");
}
查看redis数据库,如图:
1.3.5 操作ZSet有序集合——opsForZSet
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
public void optZSet(){
stringRedisTemplate.opsForZSet().add("zSet","age",29D);
}
2. 序列化机制
我们试着保存一个对象再redis中,例如:
@Test
public void optString(){
Department dep = departmentMapper.getDeptById(1);
redistemplate.opsForValue().set("dep1",dep);
}
运行,会发现报序列化错,这是因为操作对象需要是可序列化的,将department实现序列化接口即可。再次运行,运行成功,查看redis数据库,如图:
这是因为默认的序列化机制是JDK默认的序列化器,我们可以将自定义一个基于json的序列化器
改变默认序列化规则为json序列化器
@Configuration
public class MyRedisConfig {
@Bean
public RedisTemplate<Object, Department> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
RedisTemplate<Object, Department> template = new RedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
template.setDefaultSerializer(new Jackson2JsonRedisSerializer(Department.class));
return template;
}
}
注意:redisTemplate可以设置序列化器,接收类型是一个接口RedisSerializer,通过ctrl+T查看该接口实现类,如图:
可以看到有一个Jackson的序列化器,我们将该序列化器传给setDefaultSerializer即可。
运行之后,在查看redis数据库,如图:
3. 自定义缓存管理器
我们启动应用程序,在浏览器访问项目,查看redis数据库,如图:
发现,存储的不是json格式的。所以,我们希望我们存储在redis中的数据是json格式的,这时候,我们就需要自定义缓存管理器。
在boot1.5中,缓存管理器与boot2.0中的缓存管理器的处理方式是不同的,在Boot1.5中,使用 RedisTemplate 来操作redis,所以,我们的缓存管理器可以这样写
//缓存管理器
@Bean
public CacheManager cacheManager(RedisTemplate<Object, Department> redisTemplate) {
RedisCacheManager cacheManager = new RedisCacheManager(redisTemplate);
//设置缓存过期时间
cacheManager.setDefaultExpiration(10000);
cacheManager.setUsePrefix(true);
//缓存管理器
return cacheManager;
}
但是,在Boot2.0中已经不再采用这个RedisTemplate了,我们看源码
@Bean
RedisCacheManager cacheManager(CacheProperties cacheProperties, CacheManagerCustomizers cacheManagerCustomizers, ObjectProvider<org.springframework.data.redis.cache.RedisCacheConfiguration> redisCacheConfiguration, ObjectProvider<RedisCacheManagerBuilderCustomizer> redisCacheManagerBuilderCustomizers, RedisConnectionFactory redisConnectionFactory, ResourceLoader resourceLoader) {
RedisCacheManagerBuilder builder = RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(this.determineConfiguration(cacheProperties, redisCacheConfiguration, resourceLoader.getClassLoader()));
List<String> cacheNames = cacheProperties.getCacheNames();
if (!cacheNames.isEmpty()) {
builder.initialCacheNames(new LinkedHashSet(cacheNames));
}
redisCacheManagerBuilderCustomizers.orderedStream().forEach((customizer) -> {
customizer.customize(builder);
});
return (RedisCacheManager)cacheManagerCustomizers.customize(builder.build());
}
从中可以知道,Boot2.0之后的缓存管理器是通过连接工厂创建的,所以,我们在Boot2.0之后的自定义缓存管理器可以如下定义:
@Bean
public RedisCacheManager employeeRedisCacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration cacheConfiguration =
RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofDays(1)) // 设置缓存过期时间为一天
.disableCachingNullValues() // 禁用缓存空值,不缓存null校验
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new
GenericJackson2JsonRedisSerializer())); // 设置CacheManager的值序列化方式为json序列化,可加入@Class属性
return RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(cacheConfiguration).build(); // 设置默认的cache组件
}
注意:在使用boot的缓存注解缓存数据的时候,我们不用RedisTemplate,这时候,我们可以不自定义RedisTemplate,例如:
package com.bjc.config;
import com.bjc.entity.Department;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
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.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import java.net.UnknownHostException;
import java.time.Duration;
@Configuration
public class MyRedisConfig {
/*@Bean
public RedisTemplate<Object, Department> redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException {
RedisTemplate<Object, Department> template = new RedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
template.setDefaultSerializer(new Jackson2JsonRedisSerializer(Department.class));
return template;
}*/
@Bean
public RedisCacheManager employeeRedisCacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration cacheConfiguration =
RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofDays(1)) // 设置缓存过期时间为一天
//.disableCachingNullValues() // 禁用缓存空值,不缓存null校验
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new
GenericJackson2JsonRedisSerializer())); // 设置CacheManager的值序列化方式为json序列化,可加入@Class属性
return RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(cacheConfiguration).build(); // 设置默认的cache组件
}
}
浏览器访问:http://localhost:8080/getDeptById3/2
查看redis
注意:
1)如果缓存前redis中已经存在该key对应的缓存,那么运行会报错,需要先删除掉redis中的该缓存数据在执行相应的操作。
2)在Boot1.5中,使用缓存相对比较麻烦,在Boot2.0之后,全部只需要自定义缓存管理器就可以在程序中直接使用注解进行缓存操作了。