JSP 頁面翻譯為 Servlet 時,容器自動聲明九個隱式對象,無需 import、無需 new,直接在 scriptlet/表達式中使用。它們封裝了 ServletContext、HttpSession、HttpServletRequest/Response、JspWriter、PageContext、ServletConfig、異常對象,讓頁面作者專注於表現邏輯。本文按功能分類逐一拆解。
| 對象 | 類型 | 作用域 | 核心用途 |
|---|---|---|---|
| application | ServletContext | Application | 全局屬性、資源路徑、RequestDispatcher、日誌 |
| config | ServletConfig | Page | 初始化參數 (web.xml <init-param>) |
| exception | Throwable | Page | 錯誤頁面專用,封裝拋出的異常 |
| out | JspWriter | Page | 輸出流,print/println、緩衝控制 |
| page | Object (this) | Page | 當前頁面實例,極少直接用 |
| pageContext | PageContext | Page | 統一屬性管理 API、轉發/包含、獲取其它隱式對象 |
| request | HttpServletRequest | Request | 請求參數、Header、屬性、轉發/包含入口 |
| response | HttpServletResponse | Page | 設置 Header、Content-Type、重定向、Cookie |
| session | HttpSession | Session | 用戶會話屬性、登錄狀態、購物車 |
所有隱式對象均提供 setAttribute(name, value) / getAttribute(name) / removeAttribute(name),但可見範圍不同:
| 作用域 | 對象 | 生命週期 | 典型場景 |
|---|---|---|---|
| page | pageContext | 單次請求處理期間 | 標籤處理器臨時數據、頁面級緩存 |
| request | request | 一次 HTTP 請求(含轉發鏈) | Controller → JSP 傳遞模型數據、表單回顯 |
| session | session | 用戶會話(默認 30 分鐘無操作失效) | 登錄用戶信息、購物車、向導式流程中間狀態 |
| application | application | Web 應用生命週期(重啟失效) | 全局配置、緩存數據字典、計數器、DataSource |
最佳實踐:優先用 page → request → session → application,最小化作用域,減少併發衝突與內存洩漏。
均通過 RequestDispatcher 實現,獲取途徑多樣(application.getRequestDispatcher()、pageContext.getRequestDispatcher() 等)。
<%-- forward:控制權轉移,當前頁不再輸出 --%>
<%
RequestDispatcher rd = application.getRequestDispatcher("/next.jsp");
rd.forward(request, response);
%>
<%-- include:輸出合併,當前頁繼續執行 --%>
<%
RequestDispatcher rd = application.getRequestDispatcher("/header.jsp");
rd.include(request, response);
%>
區別:forward 前不可提交響應;include 適合頁首/頁尾/導航欄片段複用。
<%-- 簡單文本 --%>
<% application.log("用戶登錄: " + userId); %>
<%-- 異常+文本 --%>
<% application.log("DB 連接失敗", e); %>
實現由容器決定(文本文件、數據庫、Syslog),查閱服務器文檔定位日誌路徑。
<%-- 業務頁 --%>
<%@ page errorPage="error.jsp" %>
<%-- error.jsp --%>
<%@ page isErrorPage="true" import="java.io.*" %>
<%
// exception 隱式對象自動可用
application.log("頁面異常", exception);
%>
系統繁忙,請稍後重試
<%= exception.getMessage() %>
getParameter()、getHeader()、getCookies()、getInputStream() 讀取原始體。setContentType()、setHeader()、addCookie()、sendRedirect()。注意:不可直接調用 getWriter()/getOutputStream(),JSP 已佔用。JspWriter(緩衝 PrintWriter),print()/println()/clear()/flush()。自定義標籤處理器、大段 HTML 混雜邏輯時直接用 out 更清晰。在 web.xml 中為 JSP/Servlet 定義:
<servlet>
<servlet-name>MyJsp</servlet-name>
<jsp-file>/my.jsp</jsp-file>
<init-param>
<param-name>contactEmail</param-name>
<param-value>admin@example.com</param-value>
</init-param>
</servlet>
頁面中讀取:
<%
String email = config.getInitParameter("contactEmail");
Enumeration names = config.getInitParameterNames();
while (names.hasMoreElements()) {
String n = (String) names.nextElement();
out.println(n + "=" + config.getInitParameter(n));
}
%>
所有值為 String,需自行轉型(Integer.parseInt 等)。
removeAttribute 或 invalidate()。IllegalStateException。isErrorPage="true"**,否則 exception 不可用。response.isCommitted()。善用九大隱式對象,能寫出結構清晰、職責分離、易於維護的 JSP 應用。