一、简介
Redis作为缓存框架可以将数据存储在内存中,也可以持久化到磁盘,并且支持灾难恢复机制(服务器宕机了重启Redis服务时可以加载文件恢复缓存的数据)
Redis支持多种数据类型:string,list,set,sorted set,hash
二、使用
1.使用前需安装redis,官网地址:http://www.redis.cn/download.html,下载完成后解压,根据不同操作系统启动redis服务即可
2.pom文件引入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
application.properties相关配置:
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=localhost
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制) 默认 8
spring.redis.lettuce.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制) 默认 -1
spring.redis.lettuce.pool.max-wait=-1
# 连接池中的最大空闲连接 默认 8
spring.redis.lettuce.pool.max-idle=8
# 连接池中的最小空闲连接 默认 0
spring.redis.lettuce.pool.min-idle=0
# 存储在redis中的键名
spring.session.redis.namespace=session:redis
# session过期时间
spring.session.timeout=5m
3.编写Redis配置类:
@Configuration
@EnableCaching
public class RedisConfig extends CachingConfigurerSupport {
@Bean
public KeyGenerator cacheKeyGenerator() {
return (target, method, params) -> {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
return sb.toString();
};
}
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
// 分别创建String和JSON格式序列化对象,对缓存数据key和value进行转换
RedisSerializer<String> strSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jacksonSeial = 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);
jacksonSeial.setObjectMapper(om);
// 定制缓存数据序列化方式及时效
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofDays(1))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(strSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jacksonSeial))
.disableCachingNullValues();
return RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(config).build();
}
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
Jackson2JsonRedisSerializer 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);
//配置具体的序列化方式
RedisSerializer<String> strSerializer = new StringRedisSerializer();
//key采用String的序列化方式
template.setKeySerializer(strSerializer);
//hash的key也采用String的序列化方式
template.setHashKeySerializer(strSerializer);
template.setValueSerializer(jackson2JsonRedisSerializer);
template.setHashValueSerializer(jackson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
}
@EnableCaching开启缓存(替代掉原来的xml配置cachemanager),并且使用@Bean标记的类覆盖掉默认的类,实现自定义的一些功能
KeyGenerator:自定义键生成器,代码中定义为类的全限定名加方法名
RedisCacheManager:缓存管理器,当使用@Cacheable注解进行缓存时生效,代码中自定义缓存过期时间,并且对缓存的键值进行序列化,用来解决数据转换问题
RedisTemplate:该类可以处理复杂的对象,默认序列化方式为JdkSerializationRedisSerializer,但是实际经常想把对象以json格式进行存储,所以代码中修改了用RedisTemplate操作时的序列化方式
4.测试
@RestController
@RequestMapping("/redis")
public class RedisController {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@RequestMapping("/test1")
public String test1() {
stringRedisTemplate.opsForValue().set("aaa", "111");
return stringRedisTemplate.opsForValue().get("aaa");
}
@RequestMapping("/test2")
public Object test2() {
User user = new User();
user.setId(1);
user.setName("张三");
user.setAge(20);
ValueOperations<String, Object> operations = redisTemplate.opsForValue();
operations.set("neo", user);
return operations.get("neo");
}
@RequestMapping("/test3")
@Cacheable(value = "user-key", key = "#id", unless="#result == null")
//此处指定了key值,如果不想指定也可以用之前定义的键生成器,将key = "#id"替换成keyGenerator = "cacheKeyGenerator"即可
public User test3(Integer id) {
User user = new User();
user.setId(id);
user.setName("李四");
user.setAge(25);
System.out.println("此时没有走缓存,如果走缓存不会输出本行内容");
return user;
}
@RequestMapping("/test4")
public Object test4() {
return redisTemplate.opsForValue().get("user-key::3");
}
}
在浏览器地址输入http://localhost:8080/redis/test2时,可以打开redis desktop manager验证是否已缓存
第一次在浏览器地址输入http://localhost:8080/redis/test3?id=3时,可以看到有打印内容,代表此时没有走缓存
第二次在浏览器地址输入http://localhost:8080/redis/test3?id=3时,可以看到没有打印内容,代表此时走了缓存
在浏览器地址输入http://localhost:8080/redis/test4时,前端显示了缓存的值,代表可以通过API在其它地方根据键获取缓存
三、扩展
利用Redis可以存储session管理会话,在分布式项目中是解决共享session的方案之一
Springboot管理session也是用的内置redis方式,在pom文件引入依赖
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
编写session配置类
/**
* SpringSession Redis序列化
* *注:bean的名称必须为springSessionDefaultRedisSerializer
*/
@Component("springSessionDefaultRedisSerializer")
public class SessionConfig extends GenericJackson2JsonRedisSerializer {
}
测试:
@RequestMapping("/session")
public String uuid(HttpSession httpSession) {
UUID uuid = (UUID) httpSession.getAttribute("uuid");
if (null == uuid) {
uuid = UUID.randomUUID();
}
httpSession.setAttribute("uuid", uuid);
return httpSession.getId();
}
要想实现session共享,只需要在其它项目进行同样的配置即可