Redis序列化問題
主要會出現一下問題:
Cannot deserialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?; nested exception is java.io.InvalidClassException: com.ninebot.apr.global.beans.data.AreaNoticeInfo; class invalid for deserialization
org.springframework.data.redis.serializer.SerializationException: Cannot deserialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to deserialize payload. Is the byte array a result of corresponding serialization for DefaultDeserializer?; nested exception is java.io.InvalidClassException: com.ninebot.apr.global.beans.data.AreaNoticeInfo; class invalid for deserialization
原因:
Redis客戶端未指定序列化的方式,默認為JdkSerializationRedisSerializer序列化操作
JdkSerializationRedisSerializer:這個在多項目中反序列化會出現一個問題,反序列化的對象Bean必須與序列化對象是相同的包名才能匹配,不然出現上述問題。
解決方案:
- 建立相同包名的對象
- 改變序列化方式
Redis目前支持的序列化方式
-
JdkSerializationRedisSerializer
序列化java對像的、被序列化的對象必須實現Serializable接口
在存儲內容時,除了屬性的內容外還存了其它內容在里面,總長度長,且不容易閱讀
跨項目使用比較容易出現問題,兩邊對象必須具有相同的包名
他存儲的為二進制數據
,這對開發者是不友好的 -
GenericJackson2JsonRedisSerializer(不用指定class類型)
、JacksonJsonRedisSerializer
類似
序列化object對象為json字符串並保存到redis中,但需要和jackson配合一起使用
被序列化的對象不用實現Serializable接口
Jackson是利用反射和getter和setter方法進行讀取的,如果不想因為getter和setter方法來影響存儲,就要使用注解來定義被序列化的對象。
Jackson序列化的結果清晰,容易閱讀,而且存儲字節少,速度快,推薦。
問題:對於LocalDate等一些不太支持會報錯
還有那就是此類的構造函數中有一個類型參數,必須提供要序列化對象的類型信息(.class對象)。 通過查看源代碼,發現其在反序列化過程中用到了類型信息(必須根據此類型信息完成反序列化)GenericJackson2JsonRedisSerializer會將屬性對象轉化為Object,在反序列化時會出現轉化問題
-
StringRedisSerializer
簡單的字符串序列化,本源所在
不能序列化Bean,只能序列化字符串類型的數據 -
GenericFastJsonRedisSerializer
主要是利用了阿里爸爸的FastJson做轉化,會更快
FastJsonRedisSerializer需要指定反序列化類型,而GenericFastJsonRedisSerializer則比較通用
處理List、Set、Long類型等可能會出現問題