1 起因
(只是一个菜鸡)在某个项目时,需要用redis缓存一些数据,然后就发现从java存到redis的信息,不论是key,还是value都会有一些奇怪的符号,如下图
会多出一些\xac\xed\x00\x05t\x00,而且这样是无法在redis-cli get到值的,比如 get \xac\xed\x00\x05t\x00\x1fpromo_token_1_userId_6_itemId_6 这样得不到值,是nil
value值同样
起初我以为这样的话,java也会get不到值,然后我就开始配置redisConfig了。。。
2 redisConfig自定义配置
sp给我们提供了RedisTemplate,StringRedisTemplate
redis的基本数据类型有五种,分别String,LIst,Set,Hash,Zset(特殊类型有三种),其中String用得最多,所以会有一个StringRedisTemplate,其实StringRedisTemplate也是继承于RedisTemplate<String,String>,
StringRedisTemplated的序列化方是string,而RedisTemplate默认的序列化方式为JDK的序列化策略,所以自己配置他的序列化策略,可以用ackson2JsonRedisSerializer,GenericToStringSerializer,StringRe
disSerializer。。。
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String,Object> redisTemplate = new RedisTemplate();
//配置连接池工厂
redisTemplate.setConnectionFactory(factory);
//使用Jackson2JsonRedisSerializer的方式来序列化和反序列化redis的key和value(默认使用JDK的序列化的方式)
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
ObjectMapper om=new ObjectMapper();
// 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer抛出异常
om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
RedisSerializer stringSerializer = new StringRedisSerializer();
//使用StringRedisSerializer的方式来序列化redis的key值
redisTemplate.setKeySerializer(stringSerializer);
redisTemplate.setHashKeySerializer(stringSerializer);
//使用jackson2JsonRedisSerializer来序列化和反序列话redis的value值
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
这个这个设置很重要,我之前就是没设置这个,导致报异常(这个也是坑)
这个设置的意思就是他不会把String,Integer等类型的数据按照我们的序列化方式
om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL);
3 继续踩坑
本来以为可以愉快的玩耍了,没想到又来了。。。
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ItemModel implements Serializable {
private static final long serialVersionUID=1L;
//商品id
private Integer id;
//商品名称
private String title;
//商品价格
private BigDecimal price;
//商品库存
private Integer stock;
//商品描述
private String description;
//商品销量
private Integer sales;
//商品描述图片的url
private String imgUrl;
//活动商品信息
private PromoModel promoModel;
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class PromoModel implements Serializable {
private static final long serialVersionUID=1L;
//秒杀活动状态 1.还未开始 2.在进行中 3.已结束
private Integer status;
private Integer id;
//秒杀活动名称
private String promoName;
//秒杀活动开始的时间
DateTime startDate;
DateTime endTime;
//秒杀活动适用商品
Integer itemId;
//秒杀活动对应的价格
BigDecimal promoItemPrice;
}
当我要序列化ItemModel(当promoModel为空时序列化正常)这个类的时候,发现又乱码了,而且是很长很长,完全不知道存的是什么,就像这样
Resolved [org.springframework.data.redis.serializer.SerializationException: Could not read JSON: Cannot construct instance of `org.joda.time.chrono.ISOChronology` (no Creators, like default construct, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
根据他的报错提示,是反序列化错误,然后是缺少构造,但是我的POJO无参有参都是存在的,然后我也看到大神们说是时间问题,然后我就把Joda time的时区变为了和数据库一样的,但是没啥用啊(是我菜。。。),然后我就怀疑是不是序列化的时候就出现问题,导致反序列化就一定会有问题。
4 光明
解决的办法就是昨晚看到了一篇博客,在比较后面了。。。那个大神说,JDk的序列化方式只是在redis里存着是那样,但是可以正常存取,所以我就把RedisConfig都注掉了。。。然后就发现序列化和反序列化都正常了!!!
唉,真的是我菜,这个问题困扰了我一天半,昨天晚上才解决。。。还要努力学习!!!持续进步