Struts2 的值棧 是 **請求級** 的:每個 HTTP 請求建立一個新的值棧,隨請求結束而銷毀。<result> 類型決定值棧是否可被目標頁面存取。
| Result 類型 | 值棧傳遞 | 典型用途 |
|---|---|---|
| dispatcher (預設, JSP 轉發) | ✅ 同一請求,值棧共享 | Action → JSP 顯示資料 |
| redirect | ❌ 新請求,值棧重建 | 登入成功 → 重導首頁 (防重複提交) |
| redirectAction | ❌ 新請求,但可攜帶參數 | Action 間跳轉 |
| chain | ✅ 同一請求,值棧傳遞給下一個 Action | ActionA 處理邏輯 → ActionB 顯示 |
| stream / json / plaintext | ⚠️ 直接輸出,不經 JSP | AJAX 回應、檔案下載 |
<result>index.jsp</result> (dispatcher): 轉發到 index.jsp,同一請求,值棧內容保留,<s:debug> 可見。result type="chain" 但無後續 Action): 預設尋找 actionName-success.jsp,若不存在則 404;若直接回應 (如 AJAX),值棧隨請求結束銷毀,頁面無法存取。<s:debug> 為空: 因為該頁面屬於**上一個請求**,值棧已銷毀。<s:debug> 只能看**當前請求**的值棧。ActionContext.getContext().getSession().put("key", value); (小心記憶體洩漏)。ActionContext.getContext().getSession().put("__flash__", map); 下一請求自動取出並清除,適合重導後提示訊息。ModelDriven<T> 或提供 getter,OGNL 直接存取屬性。ActionContext.getContext().getValueStack().push(object);。理解「值棧 = 請求範圍」,配合正確的 Result 類型,即可掌控資料流向。