Struts2 開發中,經常聽到「把數據放進 Map,域對象裡也會有嗎?」這類疑問。本文從源碼角度徹底釐清 Map 與 request/session/application 原生域對象的屬性同步關係。
Struts2 最終會將 Map 中的鍵值對「平鋪」存入對應的原生域對象中。 即:map.put("key", val) 實際上等價於 request.setAttribute("key", val)(以 request 域為例)。
ActionContext.getContext().getValueStack() 獲取值棧。CompoundRoot,包含 Action 實例及 Map 結構的上下文映射。ServletActionContext.getRequest() 獲取原生 HttpServletRequest。RequestMap、SessionMap、ApplicationMap 分別實現 Map 接口,內部委託調用 request.setAttribute/getAttribute/removeAttribute。| 操作 | Map 端 | 原生域端 | 說明 |
|---|---|---|---|
| 增/改 | map.put(k,v) | request.setAttribute(k,v) | 雙向同步,實時生效 |
| 刪 | map.remove(k) | request.removeAttribute(k) | 雙向同步 |
| 查 | map.get(k) | request.getAttribute(k) | 數據源同一份 |
| 遍歷 | map.keySet() | request.getAttributeNames() | 視圖一致 |
SessionMap 委託 HttpSession,ApplicationMap 委託 ServletContext。${key} 先找值棧,再找 request、session、application;同名屬性以值棧為準。Struts2 的 Map 只是原生域對象的「Map 介面適配器」,底層數據始終存儲在 Servlet 規範定義的 request/session/application 中。