跳轉到內容

WebObjects/Web 應用程式/開發/WO 會話

來自華夏公益教科書,開放的書籍,開放的世界

WOSession 提供了與使用者使用您的應用程式相關的所有狀態的封裝。每個 WebObjects 應用程式都有其自己的 WOSession 子類,這是 WebObjects 中的會話跟蹤與 J2EE 之間的重要區別。在 J2EE 中,HttpSession 沒有子類化,所有狀態都儲存在 HttpSession 的 Map 中的屬性中。在 WebObjects 中,會話更豐富,提供了利用作為完整類(型別化欄位、方法等)的所有優勢的能力。WOSessions 具有超時時間,預設情況下在 WOApplication 配置中配置。此超時時間決定伺服器在沒有活動請求的情況下保持會話處於活動狀態的時間。當會話超時時,它將被垃圾回收。

訪問會話

[編輯 | 編輯原始碼]
 Session session = (Session)session();

請注意,此方法僅在 WOComponent 或 WODirectAction 子類中有效。如果您想從其他地方訪問會話,請從以下列表中選擇一個答案

  • 您的設計有誤;不要從該類訪問會話。
  • 建立並維護一個索引,指示哪個執行緒正在處理哪個會話,然後您始終可以從任何地方找到當前會話。
  • 僅執行單執行緒,並維護一個儲存,指示哪個會話是當前的。
  • 從呼叫元件或直接操作中傳遞會話。但是,請參閱第一項。

只需再提醒一句,不要將會話設定為 WOComponent 或 WODirectAction 的類變數,這將建立一個迴圈並阻止舊會話被垃圾回收。

以上情況真的嗎?在 WO5 純 Java 應用程式中,像這樣的迴圈引用可能會為垃圾收集器增加更多工作量,但不會阻止任何內容被垃圾回收。Java 垃圾收集器應該能夠很好地處理迴圈引用。-- JonathanRochkind

如果您想簡化程式碼,只需在您的元件中插入以下方法(這將節省您的輸入量)

 public Session Session() {
   return (Session)this.session();
 }

我們始終從一個 WOComponent 子類開始我們的專案,我們將其用作所有其他元件的超類。我們包含此方法以及其他一些有用的實用程式方法。-- JoshuaMarker

我記得關於將對 Session 的引用儲存在 Session 的內部類中的警告。在另一個元件中儲存對 Session 的引用是完全可以的,儘管訪問器方法更好。-- BrianMarquis

我仍然認為這在 WO5 中不是問題,儘管它可能在 WO4.5 中存在。JRE 1.3.1 應該能夠很好地垃圾回收迴圈引用,無論是否涉及內部類。但也許 JRE 沒有做它應該做的事情?-- JonathanRochkind

會話跟蹤

[編輯 | 編輯原始碼]

當第一次為請求請求會話時,WebObjects 確保來自同一使用者的後續所有請求都將使用相同的 WOSession 例項。WebObjects 使用以下三種技術之一來實現此會話跟蹤:URL 重寫、cookie 或查詢字串。

使用 URL 重寫,一旦會話初始化,生成的 URL 將在 URL 路徑中包含會話 ID。例如,如果您使用 WOHyperlink,生成的 URL 將類似於“http://hostname.com/cgi-bin/WebObjects/AppName.woa/1/wo/EMVnGH1g8VLOW2TRMm3Ptg/6.0.19.15.1.3.1”。此示例中的“EMVnGH1g8VLOW2TRMm3Ptg”是唯一生成的會話 ID。所有帶有此會話 ID 的 URL 的請求都將附加到相同的 WOSession 例項。

Cookie 的工作原理類似,只是它們不重寫 URL 來傳遞會話 ID,而是將會話 ID 傳遞給名為“wosid”的 cookie。

最後,您可以傳遞一個名為“wosid”的查詢字串屬性,其中包含會話 ID。這通常用於呼叫需要訪問使用者會話的 DirectAction。

效能影響

[編輯 | 編輯原始碼]

由於保持會話處於活動狀態所需的記憶體使用量,因此必須仔細監控大型部署中的會話建立和永續性。通常建議儘可能減少會話建立。當使用“正常”WebObjects 技術時,這可能很困難。例如,WOHyperlink 的預設行為是在呼叫 WOComponent 上的操作時導致建立會話。避免建立會話的典型方法是使用 DirectAction 實現您的應用程式。DirectAction 不需要建立頁面快取來儲存頁面狀態,因此可以用完全無狀態的方式使用。僅使用 DirectAction 的缺點是您將失去更具狀態的方法的好處。例如,當僅使用 DirectAction 時,您會發現您必須透過解釋查詢字串變數來手動連線您的狀態物件。

您可以透過呼叫 existingSession() 方法檢查 DirectAction 中是否存在會話。如果存在會話,則將返回該會話。如果尚未建立會話,則此方法將返回 null。

調整會話超時時間會對效能產生重大影響。會話超時時間越長,會話消耗的記憶體就越多。在負載很重的情況下,“死”會話會不斷積累,因此應將超時時間調整為儘可能低,但不會對使用者使用您的應用程式的體驗產生負面影響。

掛起會話

[編輯 | 編輯原始碼]

在 WebObjects 中,某些情況下,丟擲的異常會導致會話未被檢回 WOSessionStore,這將使會話死鎖。這種情況的常見原因之一是使用會話的 DirectAction 丟擲的異常。如果您使用 Project Wonder 的 ERXApplication、ERXSession 等,它提供了防止此問題的機制。但是,如果您使用的是沒有 Project Wonder 的預設 WebObjects 安裝,則需要自己解決此問題。在這種情況下,您不應該讓您的 DirectAction 丟擲異常。

檢查現有會話

[編輯 | 編輯原始碼]

如果您在嘗試執行此操作時位於 DirectAction 方法中,請檢查以下 WOAction 方法(WOAction 是 WODirectAction 的超類)

 public WOSession existingSession()

根據請求恢復會話。如果請求沒有會話 ID 或會話 ID 引用了不存在的會話,則此方法返回 null。若要確定會話是否未恢復,請檢查請求的會話 ID,檢視它是否為非空,如果是,請呼叫此方法檢查其結果。

返回值:一個 WOSession 物件,它代表向特定客戶端授予對 WebObjects 應用程式及其資源的訪問許可權的期間

如果您不在 DirectAction 方法中,請檢視 WOContext 的方法

 public boolean hasSession()

如果接收上下文中存在會話,則返回 true,否則返回 false。

華夏公益教科書