您好,登錄后才能下訂單哦!
本篇文章為大家展示了Tomcat中Session對象部分屬性值丟失問題的分析與解決是怎樣的,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。
我們最近的一個 Java 項目在從開發環境遷移到測試環境之后,遇到了一個非常詭異的問題——在將一個 Java 對象存儲到 SESSION 會話中而后從中取出時,這個對象的部分屬性在 SESSION 會話剛創建的一段時間內是正確的,但是一段時間過后,雖然SESSION沒有失效,但是這部分屬性的值卻變成NULL了。更令人奇怪的是,無論是變成NULL的屬性,還是未變成NULL的屬性,都是最簡單的String類型變量,實在讓人看不明白他們之間到底有何不同。
為了將問題表述清楚,下面我舉個例子來詳細說明下。我們定義的類信息大概如下圖所示:
其中,SessionBean是我們將要放到SESSION中的對象,而BaseBean則是SessionBean繼承的父類。無論是在開發還是測試環境,SessionBean對象都可以不拋出任何異常地存取值,但是其中的屬性則不一定:屬性a和屬性b在SESSION創建之后,只要SESSION沒有失效,就一直可以正常讀取其值;但是其中的屬性c,只在SESSION創建不久的一段時間內有效,如果一段時間后再取值,屬性c的值就變成NULL了。沒有任何認為操作,變量值卻改變了,是不是很神奇?
【問題根源】
中間的具體排查過程我就不講了,反正經過好長一段時間的分析和排查,問題的根源終于找到了—— BaseBean沒有繼承Serializable接口!
【原因剖析】
下面我結合上文以及我對 Tomcat 服務器SESSION會話管理原理的分析,來給大家解釋下,為什么僅僅少繼承了一個可序列化接口(Serializable),就會出現如此詭異的問題。
首先,在SESSION創建的時候,SessionBean對象中的所有屬性(a、b、c),都可以正常寫入到SESSION會話中,這點是沒有問題的。對于剛剛創建的SESSION,此時其內容都保存在服務器的內存當中,如果這時候讀取SEESION, Tomcat 直接把內存中的內容返回給調用者就OK了,所以返回的屬性值都是正確的。
而后,無論是因為Tomcat占用內存超出了閾值也好,還是Tomcat定期保存SESSION現場也罷,反正都會引起接下來的操作——將SESSION會話持久化。在將數據從內存寫入硬盤的過程中,就涉及了一個非常重要的問題:數據要寫入硬盤,應該以什么樣的格式存儲,又應該怎樣把它變成相應的格式?這就是——序列化!
通過觀察上圖中的代碼我們不難發現,SessionBean對象已經實現了Serializable接口,所以在將SessionBean對象保存到磁盤的過程中,也就是對對象進行序列化操作的時候,是不會報任何錯誤的,這也是我們難以通過跟蹤錯誤日志來定位問題的根本原因。但是因為SessionBean的基類BaseBean沒有實現Serializable接口,所以BaseBean中的屬性c在進行序列化的時候就沒能保存下來,進而在反序列化的時候,屬性c的值就變成NULL了。所以我們讀出的值也莫名其妙變成了NULL也就不難理解了。
【解決方案】
至于解決方案,很簡單,給基類BaseBean加個Serializable接口就搞定了嘛。
【問題反思】
此次問題帶給我們的反思主要有兩個:
第一,對于SESSION會話中保存的類,一定要確保該類以及該類的父類實現了Serializable接口,否則無法將類中的屬性序列化。
第二,在進行業務邏輯操作之前,一定要對所有具有不確定性的值的合法性進行安全校驗(防御性編程),此次若不是我“多此一舉”,在業務邏輯前對這個基本可以認定正確(因為寫入完全可控可信)的屬性c進行了合法性校驗,這個神奇的問題還說不定什么時候才能發現呢。
上述內容就是Tomcat中Session對象部分屬性值丟失問題的分析與解決是怎樣的,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。