首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Liferay Portlet Session 處理深度解析 (二):實現機制與 getSession(true) 陷阱

     編輯:Java 相關知識

Liferay 實現:PortletSession 其實是 Portal 級 HttpSession

在 RenderRequestImpl/ActionRequestImpl 建構時:

_ses = new PortletSessionImpl(_req.getSession(), _portletName, _portletCtx);

_req.getSession() 取得的是 Portal System 全域的 HttpSession。因此:

  • 無論呼叫 getSession() 或 getPortletSession(),拿到的都是同一個 Portal 級 Session 物件。
  • 不同 Portlet Application 共用同一 Session,未實現規範要求的「每個 Portlet App 擁有私有 Session」。

開發者易踩坑:習慣用 request.getSession()

Liferay 提供 getPortletSession(),但開發者慣用 getSession() 導致無法隔離屬性作用域。

PortletServletRequest 缺少 getSession(boolean) 導致 NPE

PortletRequestDispatcherImpl.include() 產生 PortletServletRequest 時:

public PortletServletRequest(HttpServletRequest req, ...) {
    super(req);
    _ses = req.getSession(); // 仍是 Portal Session
}

它實作了 getSession() 但未實作 getSession(boolean create)。當 JSP/Servlet 呼叫 request.getSession(true) 時,父類 ApplicationHttpRequest 邏輯會嘗試在當前 Web App Context 尋找/建立 Session,卻只能在 Portal Context 找到,導致 localSession == null 拋出 NullPointerException。

根因堆疊

ApplicationHttpRequest.getSession(true)
    → context.getManager().findSession(other.getId()) // Portal Context 找不到當前 Web App 的 Session
    → localSession 為 null
    → localSession.access() → NPE

建議

  1. Portlet 開發統一使用 request.getPortletSession() 並指定 PORTLET_SCOPE / APPLICATION_SCOPE。
  2. 避免在 Portlet 包含的 Servlet/JSP 中呼叫 request.getSession(true)。
  3. 期待 Liferay 修補 PortletServletRequest 實作完整 Session 介面。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved