您好,登錄后才能下訂單哦!
這篇文章主要介紹“使用Spring Session管理分布式會話時遇到的反序列化問題怎么解決”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“使用Spring Session管理分布式會話時遇到的反序列化問題怎么解決”文章能幫助大家解決問題。
問題浮現
我們在使用SpringSession時(其實在問題出現時,我們并沒有意識到和這兒有關聯),遇到了一個隱藏較深的問題。我們像往常一樣,在用戶登錄成功之后,將用戶的實體類信息實例化保存到了session中,且session最后保存到了redis里面,這個過程其實是沒有什么問題的。
隨著時間的推移業務的迭代變化,用戶實體需要為更新的需求增加額外的字段,于是我們順其自然的在類中追加其他String類型的屬性,結果上了測試環境,發現我們無法進入到登錄頁面,從瀏覽器控制臺上我們發現這個請求因為無法獲取正確的鑒權而不斷報302,并且瀏覽器錯誤主頁提示我們“清除瀏覽器cookie”,當我們照做之后,登錄頁面神奇般的可以打開并且我們能夠順利登錄系統和使用系統了。在我們回到服務端查看后臺日志時,我們看到時在redis中出現了反序列化的問題,而且日志報的很蹊蹺,并不是我們的業務代碼的某一行直接拋出的日志,這給我們定位問題帶了一點麻煩。
分析問題
首先反序列化出現問題,我們首先能夠想到的就是給用戶實體加了額外屬性導致的,但是為何會出現反序列化問題呢?原因看起來很簡單,我們的用戶實體類確實實現了Serializable接口,但是我們并沒有顯示的寫出序列化的serialVersionUID,這在實體變更了屬性字段之后反序列化回來,就一定會反序列化失敗的,因為在你沒有指定序列號serialVersionUID號的時候,系統默認都是以類名稱類屬性等來自動生成的,不同的屬性名稱得出的序列化值肯定是不一樣的,解決的方法很簡單,就是在初始化類的時候,主動寫名序列化serialVersionUID號。
但是我們的程序現在已經在生產環境了,無法做到這一步,因為按照新的類來生成序列號,顯然是前后不一致的,給新加的字段加上transient字段?這種做法也步行,這意味著這個字段的值將無法序列化,后面其他系統肯定是使用不了的,這些額外增加的字段就沒有存在意義了。
在對報錯日志進行抽絲剝繭逐行分析之后,發現這個異常居然和SpringSession有關系。
因為我們在用戶成功登錄系統之后,使用了request.getSession()。setAttribute("xx", "xx")操作,我們將我們的用戶實體放到了session中,并由SpringSession成功的放到了Redis里面,并且我們的會話時長是48小時;在我們新的實體更新進來之后,系統一發布,打開登錄頁面系統對SpringSession中的內容進行初始化,就發現了用戶實體無法從Redis中初始化回來,因為前后的序列化號對不上了,于是就瘋狂的報反序列化失敗,這是根本問題所在。
解決問題
那怎么解決呢?很明顯,聰明的瀏覽器給了我們第一個解決方案,那就是清除瀏覽器Session。
因為上面我們說到,SpringSession會在瀏覽器里面自動設置一個名為SESSION的cookie值,這個值是為了后臺服務能夠在Redis中找到之前存放的Session以便能夠識別是統一用戶,當瀏覽器清除了Cookie之后,這個SESSION的值就失去了,于是系統重新為這個瀏覽器發起請求的用戶重新生成SESSION值,這個請求也就無法在redis中找到對應的Session會話,也就沒有將用戶實體反序列化這個過程,登錄程序當然能夠正常進行,而且往后的交互都是正常的了。
那么還有另外的解決方法,從Redis端,既然SpringSession會用這個SESSION去Redis中找對應的值,那么我們就將這個Redis中存放的Session內容進行清除,找不到內容自然就無需反序列化了,不過此時正常訪問的用戶,也會因為請求沒有找到統一的Session而認為是會話過期強制退出。這里在redis中清除內容的方式,可以使用下面的命令:
$ redis-cli keys '*' | xargs redis-cli del
$ redis-cli del spring:session:sessions:7e8383a4-082c-4ffe-a4bc-c40fd3363c5e
第三種方式呢,就是從代碼端改造,反序列化失敗的本質就是原來的類新增了屬性,而且類沒有顯示的指定序列化serialVersionUID,那么我們變通一下,保持原來的類不變唄,新增的屬性放到一個繼承了這個用戶實體類的類當中,后面我們就用這個新的類,保持老的類不變(屬性類型和數量等的都不變),那就行了。是的,就是使用新類的方式,新類繼承用戶實體類,保持用戶實體類不變,新類當中增加需要補充的屬性字段,同時需要序列化,這樣SpringSession在初始化時,它依然能夠反序列找到原來沒有變通的那個類,我們自己也能夠很好的實現我們新的需求了。
關于“使用Spring Session管理分布式會話時遇到的反序列化問題怎么解決”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。