JSP頁面中的對象——無論是用戶創建的JavaBean,還是容器提供的九大隱含對象——均具備「作用域」屬性。作用域定義了對象的可見生命週期與跨頁面訪問邊界。掌握四大作用域(page、request、session、application)的差異與適用場景,是構建高效、可維護Web應用的關鍵。
| 作用域 | 綁定容器 | 生命週期 | 典型應用場景 |
|---|---|---|---|
| page | PageContext |
單次請求處理期間(含include、forward前) |
頁面內臨時數據傳遞、標簽協作 |
| request | ServletRequest |
單次HTTP請求鏈(含forward/include目標頁) |
請求鏈數據共享、MVC模式下Controller向View傳值 |
| session | HttpSession |
用戶會話期間(默認30分鐘無操作超時) | 用戶登錄狀態、購物車、多步向導表單數據 |
| application | ServletContext |
Web應用全生命週期(容器啟動至關閉) | 全局配置、緩存數據、計數器、數據源引用 |
<!-- test1.jsp -->
<%
pageContext.setAttribute("name", "zhangsan");
out.println("test1.jsp: " + pageContext.getAttribute("name") + "<p>");
pageContext.include("test2.jsp");
%>
<!-- test2.jsp -->
<%
out.println("test2.jsp: " + pageContext.getAttribute("name"));
%>
輸出:
test1.jsp: zhangsan
test2.jsp: null
結論:page作用域不隨include/forward傳遞。
<!-- test1.jsp -->
<%
request.setAttribute("name", "zhangsan");
out.println("test1.jsp: " + request.getAttribute("name") + "<p>");
pageContext.include("test2.jsp");
%>
<!-- test2.jsp -->
<%
out.println("test2.jsp: " + request.getAttribute("name"));
%>
輸出:
test1.jsp: zhangsan
test2.jsp: zhangsan
結論:request作用域隨forward/include傳遞。若註釋include、分兩次獨立請求,test2.jsp將輸出null,證明新請求創建新request對象。
同一瀏覽器會話內,不同請求、不同頁面均可訪問session.setAttribute存入的數據,直至會話超時或調用invalidate()。
應用部署後,所有用戶、所有頁面共享同一ServletContext實例,適合存放只讀配置、連接池、全局緩存等。
synchronized或使用ConcurrentMap。removeAttribute,防止內存洩漏。精準選擇作用域,不僅關乎功能正確,更直接影響系統擴展性與資源佔用。建議在設計階段即明確數據流轉邊界,將作用域選型納入架構決策。