最近在整合redis时老是遇到一些奇奇怪怪的问题,今天记录一下,避免以后再遇到,首先是配置文件
@Component
public class RedisConfig {
public static final Duration DEFAULT_ENTRY_TTL = Duration.ofMinutes(10);
@Bean
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
return redisTemplateConfig(connectionFactory);
}
public RedisTemplate<String, Object> redisTemplateConfig(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
//使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值(默认使用JDK的序列化方式)
Jackson2JsonRedisSerializer<Object> serializer = jsonRedisSerializer();
StringRedisSerializer stringSerializer = stringRedisSerializer();
template.setKeySerializer(stringSerializer);
template.setValueSerializer(serializer);
//hashKey类型必须用String 可以避免一些序列化和反序列化的问题
template.setHashKeySerializer(stringSerializer);
//hashValue 数字类型不用用long 反序列化回来有问题
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
private Jackson2JsonRedisSerializer<Object> jsonRedisSerializer() {
Jackson2JsonRedisSerializer<Object> serializer = new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
//解决jackson2无法反序列化LocalDateTime的问题
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
mapper.registerModule(getJavaTimeModule());
//补充:日期格式的HH务必要大写 @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
serializer.setObjectMapper(mapper);
return serializer;
}
private JavaTimeModule getJavaTimeModule(){
JavaTimeModule javaTimeModule = new JavaTimeModule();
/* DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
javaTimeModule.addSerializer(LocalDateTime.class,
new LocalDateTimeSerializer(dtf));
javaTimeModule.addDeserializer(LocalDateTime.class,
new LocalDateTimeDeserializer(dtf));*/
return javaTimeModule;
}
private StringRedisSerializer stringRedisSerializer() {
return new StringRedisSerializer();
}
@Bean(name = "redisCacheManager")
public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(DEFAULT_ENTRY_TTL)
.disableCachingNullValues()
//修改 结构 树化显示 默认是两个冒号有问题
.computePrefixWith(cacheName -> cacheName + ":")
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(stringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jsonRedisSerializer()));
/* if (cacheProperties.getRedis().getTimeToLive() != null) {
config = config.entryTtl(cacheProperties.getRedis().getTimeToLive());
}*/
return RedisCacheManager.builder(redisConnectionFactory).cacheDefaults(config).build();
}
}
问题一: Long类型转String类型
这个redisTemplate 在序列化Long类型老是出问题,因为redis就支持Integer 不支持Long
主要是我的Id都是Long类型所以容易出问题
一个是Hash类型 在填HashKey的时候, 因为用的是String类型的序列化, 这里不推荐改成Jackson2的序列化
直接在存储的key那里转成String就好.
另:
还有一个,不只是Key, value也会有问题
因为有一些计数的进行累加,比如阅读量这种,建议使用integer类型, 不然使用Long类型存入的时候没有问题
但是读取出来反序列化的时候会报错就是了!
问题二: loclaDateTime 类型序列化
上面的配置已经解决了这个问题, 但是有一个问题是配置解决不了的, 就是我们在类里面输出的json格式
小时的HH一定要用大写,不要用小写,不然转换会报错,格式没关系,但是这些时间日期的大小写一定要这样!
@ApiModelProperty(value = "创建时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;