溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

Tomcat中Session對(duì)象部分屬性值丟失問(wèn)題的分析與解決是怎樣的

發(fā)布時(shí)間:2021-12-07 11:41:00 來(lái)源:億速云 閱讀:396 作者:柒染 欄目:服務(wù)器

本篇文章為大家展示了Tomcat中Session對(duì)象部分屬性值丟失問(wèn)題的分析與解決是怎樣的,內(nèi)容簡(jiǎn)明扼要并且容易理解,絕對(duì)能使你眼前一亮,通過(guò)這篇文章的詳細(xì)介紹希望你能有所收獲。

我們最近的一個(gè) Java 項(xiàng)目在從開(kāi)發(fā)環(huán)境遷移到測(cè)試環(huán)境之后,遇到了一個(gè)非常詭異的問(wèn)題——在將一個(gè) Java 對(duì)象存儲(chǔ)到 SESSION  會(huì)話(huà)中而后從中取出時(shí),這個(gè)對(duì)象的部分屬性在 SESSION  會(huì)話(huà)剛創(chuàng)建的一段時(shí)間內(nèi)是正確的,但是一段時(shí)間過(guò)后,雖然SESSION沒(méi)有失效,但是這部分屬性的值卻變成NULL了。更令人奇怪的是,無(wú)論是變成NULL的屬性,還是未變成NULL的屬性,都是最簡(jiǎn)單的String類(lèi)型變量,實(shí)在讓人看不明白他們之間到底有何不同。

為了將問(wèn)題表述清楚,下面我舉個(gè)例子來(lái)詳細(xì)說(shuō)明下。我們定義的類(lèi)信息大概如下圖所示:

Tomcat中Session對(duì)象部分屬性值丟失問(wèn)題的分析與解決是怎樣的

其中,SessionBean是我們將要放到SESSION中的對(duì)象,而B(niǎo)aseBean則是SessionBean繼承的父類(lèi)。無(wú)論是在開(kāi)發(fā)還是測(cè)試環(huán)境,SessionBean對(duì)象都可以不拋出任何異常地存取值,但是其中的屬性則不一定:屬性a和屬性b在SESSION創(chuàng)建之后,只要SESSION沒(méi)有失效,就一直可以正常讀取其值;但是其中的屬性c,只在SESSION創(chuàng)建不久的一段時(shí)間內(nèi)有效,如果一段時(shí)間后再取值,屬性c的值就變成NULL了。沒(méi)有任何認(rèn)為操作,變量值卻改變了,是不是很神奇?

【問(wèn)題根源】

中間的具體排查過(guò)程我就不講了,反正經(jīng)過(guò)好長(zhǎng)一段時(shí)間的分析和排查,問(wèn)題的根源終于找到了—— BaseBean沒(méi)有繼承Serializable接口!

【原因剖析】

下面我結(jié)合上文以及我對(duì) Tomcat  服務(wù)器SESSION會(huì)話(huà)管理原理的分析,來(lái)給大家解釋下,為什么僅僅少繼承了一個(gè)可序列化接口(Serializable),就會(huì)出現(xiàn)如此詭異的問(wèn)題。

首先,在SESSION創(chuàng)建的時(shí)候,SessionBean對(duì)象中的所有屬性(a、b、c),都可以正常寫(xiě)入到SESSION會(huì)話(huà)中,這點(diǎn)是沒(méi)有問(wèn)題的。對(duì)于剛剛創(chuàng)建的SESSION,此時(shí)其內(nèi)容都保存在服務(wù)器的內(nèi)存當(dāng)中,如果這時(shí)候讀取SEESION,  Tomcat 直接把內(nèi)存中的內(nèi)容返回給調(diào)用者就OK了,所以返回的屬性值都是正確的。

而后,無(wú)論是因?yàn)門(mén)omcat占用內(nèi)存超出了閾值也好,還是Tomcat定期保存SESSION現(xiàn)場(chǎng)也罷,反正都會(huì)引起接下來(lái)的操作——將SESSION會(huì)話(huà)持久化。在將數(shù)據(jù)從內(nèi)存寫(xiě)入硬盤(pán)的過(guò)程中,就涉及了一個(gè)非常重要的問(wèn)題:數(shù)據(jù)要寫(xiě)入硬盤(pán),應(yīng)該以什么樣的格式存儲(chǔ),又應(yīng)該怎樣把它變成相應(yīng)的格式?這就是——序列化!

通過(guò)觀察上圖中的代碼我們不難發(fā)現(xiàn),SessionBean對(duì)象已經(jīng)實(shí)現(xiàn)了Serializable接口,所以在將SessionBean對(duì)象保存到磁盤(pán)的過(guò)程中,也就是對(duì)對(duì)象進(jìn)行序列化操作的時(shí)候,是不會(huì)報(bào)任何錯(cuò)誤的,這也是我們難以通過(guò)跟蹤錯(cuò)誤日志來(lái)定位問(wèn)題的根本原因。但是因?yàn)镾essionBean的基類(lèi)BaseBean沒(méi)有實(shí)現(xiàn)Serializable接口,所以BaseBean中的屬性c在進(jìn)行序列化的時(shí)候就沒(méi)能保存下來(lái),進(jìn)而在反序列化的時(shí)候,屬性c的值就變成NULL了。所以我們讀出的值也莫名其妙變成了NULL也就不難理解了。

【解決方案】

至于解決方案,很簡(jiǎn)單,給基類(lèi)BaseBean加個(gè)Serializable接口就搞定了嘛。

【問(wèn)題反思】

此次問(wèn)題帶給我們的反思主要有兩個(gè):

第一,對(duì)于SESSION會(huì)話(huà)中保存的類(lèi),一定要確保該類(lèi)以及該類(lèi)的父類(lèi)實(shí)現(xiàn)了Serializable接口,否則無(wú)法將類(lèi)中的屬性序列化。

第二,在進(jìn)行業(yè)務(wù)邏輯操作之前,一定要對(duì)所有具有不確定性的值的合法性進(jìn)行安全校驗(yàn)(防御性編程),此次若不是我“多此一舉”,在業(yè)務(wù)邏輯前對(duì)這個(gè)基本可以認(rèn)定正確(因?yàn)閷?xiě)入完全可控可信)的屬性c進(jìn)行了合法性校驗(yàn),這個(gè)神奇的問(wèn)題還說(shuō)不定什么時(shí)候才能發(fā)現(xiàn)呢。

上述內(nèi)容就是Tomcat中Session對(duì)象部分屬性值丟失問(wèn)題的分析與解決是怎樣的,你們學(xué)到知識(shí)或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識(shí)儲(chǔ)備,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI