最近在使用蓝绿部署时出现一个问题:
从redis取出缓存的用户数据时,出现org.springframework.data.redis.serializer.SerializationException: Could not read JSON: Unrecognized field "signImg" 这个错误.
后来查看代码时发现原因是 redis使用Jackson2JsonRedisSerializer存储用户信息时,会把类名和类属性存进redis, 再从redis读取数据时,它会根据类名自动转换类型.
redis存储的数据是这样的:
["com.kb.Customer",{"id":1,"signImg":1}]
而蓝绿部署时 ,老版本的代码Customer类中没有signImg这个属性,这时取出redis数据就会报刚才的错误.
结合报错信息并调试redisTemplate源码时发现:
源码中jackson会根据缓存的字段,依次去类中寻找是否存在这个字段,如果不存在就会抛出刚才的异常. 这里可以发现有个_ignorabieProps属性,可以看出这是一个忽略属性名单.
所以解决这个错误只需要把类中没有的属性加进这个忽略名单就行了.于是搜索了一波jackson handleUnknownVanilla这个异常
找到的解决办法是在实体类上加上注解@JsonIgnoreProperties(ignoreUnknown = true)
再次调试,问题解决.
最后,感觉这样的序列化方式容易出问题, 比如A项目缓存了kb.Customer类, 此时B项目需要读取这个缓存,但B项目中没有这个Customer类或者包名不一样 也会报刚才的错误. 我个人倾向于redis缓存时不要用jackson的自动类型转换,仅存储 类的json值,取出时再自己转换. 由于是老项目,存在很多这样的代码,改起来也费时费劲,以后再慢慢寻找这个问题的解决办法