整合redis
- springboot在现在的版本中操作Redis数据库用到了lettuce,而不是Jedis,他们各有各的特点。
- Jedis以Redis命令作为方法名称,学习成本低,简单实用。但是Jedis实例是线程不安全的,多线程环境下需要基于连接池来使用。
- Lettuce是基于Netty实现的,支持同步、异步和响应式编程方式,并且是线程安全的。支持Redis的哨兵模式、集群模式和管道模式。
SpringDataRedis相关的api
1、引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2、配置文件
spring:
redis:
# Redis服务器地址
host: 127.0.0.1
# Redis服务器端口号
port: 6379
# 使用的数据库索引,默认是0
database: 0
# 连接超时时间
timeout: 1800000
# 设置密码
password: "123456"
3、代码测试
@Autowired
private RedisTemplate redisTemplate;
@Test
public void redis() {
redisTemplate.opsForValue().set("study","学习redis");
String name = (String) redisTemplate.opsForValue().get("study");
System.out.println(name);
}
问题出现了:当我们使用Redis客户端查看刚刚存入Redis数据库的数据时,结果是这样的:
是因为在使用默认的对象redisTemplate时,会把value值序列化为byte类型,所以就出现了上图的结果。
同理,如果我们存储内容是对象的时候,不序列化的话会报错
因此我们需要自定义序列化器
public void redis(){
User user = new User();
user.setName("zs");
user.setDeptId("11");
user.setAge(20);
redisTemplate.opsForValue().set("user:info",user);
}
报错:
因此我们需要自定义序列化器
4、自定义序列化器
@Configuration
public class RedisCacheManagerConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 设置Key的序列化方式
template.setKeySerializer(new StringRedisSerializer());
// 设置Value的序列化方式,根据需求选择
template.setValueSerializer(jackson2JsonRedisSerializer());
// 同样可以设置hashKey和hashValue的序列化方式
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
return template;
}
// 配置Jackson2JsonRedisSerializer
// 避免出现获取缓存时出现的类型转换错误
private Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer() {
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer =
new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.configure(MapperFeature.USE_ANNOTATIONS, false);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
// 此项必须配置,否则会报java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to XXX
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
return jackson2JsonRedisSerializer;
}
}
再次执行存储对象,存储字符串
整合redisCahemanager
在上述redis配置中增加cacheMangerp配置
@Configuration
public class RedisCacheManagerConfig {
@Bean
public CacheManager cacheManager(RedisConnectionFactory connectionFactory) {
// 若想存入的不包含类信息,就直接使用GenericJackson2JsonRedisSerializer,配合ObjectMapper
ObjectMapper objectMapper = new ObjectMapper();
GenericJackson2JsonRedisSerializer serializer = new GenericJackson2JsonRedisSerializer(objectMapper);
//------------------------//
RedisCacheConfiguration cacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer()))
//变双冒号为单冒号
.computePrefixWith(name -> name +":");
return RedisCacheManager.builder(connectionFactory)
.cacheDefaults(cacheConfiguration)
.build();
}
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 设置Key的序列化方式
template.setKeySerializer(new StringRedisSerializer());
// 设置Value的序列化方式,根据需求选择
template.setValueSerializer(jackson2JsonRedisSerializer());
// 同样可以设置hashKey和hashValue的序列化方式
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
return template;
}
// 配置Jackson2JsonRedisSerializer
// 避免出现获取缓存时出现的类型转换错误
private Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer() {
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer =
new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
objectMapper.configure(MapperFeature.USE_ANNOTATIONS, false);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
// 此项必须配置,否则会报java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to XXX
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
return jackson2JsonRedisSerializer;
}
}
使用参考springCache本地缓存:
简单测试:
@Component
public class UserCache {
@Cacheable(cacheNames = "room")
public User getUserId(String userId){
User user = new User();
user.setId(userId);
user.setAge(10);
user.setDeptId("1");
user.setName("zs");
user.setSex("男");
return user;
}
}
@Autowired
private UserCache userCache;
@Test
public void cache(){
User user = userCache.getUserId("1");
System.out.println(user);
}
结果: