ExternalContext 核心定位
ExternalContext 為 JSF 提供與底層容器 (Servlet/Portlet) 解耦的統一訪問層。通過 FacesContext.getCurrentInstance().getExternalContext() 獲取實例,封裝了 ServletContext, ServletRequest, ServletResponse, HttpSession 等原生對象,並提供 Map 風格 API 便捷操作屬性與參數。
核心對象獲取
| 方法 | 返回類型 | 對應原生對象 | 用途 |
| getContext() | Object | ServletContext | Web 應用上下文,資源載入、全局屬性、初始化參數 |
| getRequest() | Object | ServletRequest | 當前請求,參數、Header、屬性、輸入流 |
| getResponse() | Object | ServletResponse | 當前響應,輸出流、Header、狀態碼、Cookie |
注意: 返回 java.lang.Object 而非 Servlet 具體類型,保證 JSF 實現可移植至 Portlet 等非 Servlet 容器。
作用域屬性 Map API (推薦使用)
| Map 方法 | 對應作用域 | 原生對應 | 典型場景 |
| getApplicationMap() | Application | ServletContext 屬性 | 全局單例緩存、數據源、配置對象 |
| getSessionMap() | Session | HttpSession 屬性 | 用戶會話狀態、購物車、權限緩存 |
| getRequestMap() | Request | ServletRequest 屬性 | 請求級數據傳遞、跨組件通信 |
// 統一訪問模式
Map<String, Object> sessionMap = externalContext.getSessionMap();
if (sessionMap != null) {
User user = (User) sessionMap.get("currentUser");
sessionMap.put("preferences", new Preferences());
}
Session 管理
getSession(boolean create):對應 HttpServletRequest.getSession(create)。true 強制創建,false 僅獲取現有或返回 null。
invalidateSession():銷毀 Session。
getSessionMaxInactiveInterval() / setSessionMaxInactiveInterval(int):讀寫超時時間 (秒)。
初始化參數
getInitParameter(String name):讀取 web.xml 中 <context-param>。
getInitParameterMap():獲取所有上下文參數 Map。
請求參數與 Header
| 方法 | 返回 | 說明 |
| getRequestParameterMap() | Map<String, String> | 單值參數 (同 getParameter),Key=參數名,Value=首個值 |
| getRequestParameterValuesMap() | Map<String, String[]> | 多值參數 (同 getParameterValues),Value=字符串數組 |
| getRequestParameterNames() | Iterator<String> | 所有參數名迭代器 (替代 Enumeration) |
| getRequestHeaderMap() | Map<String, String> | 單值 Header (大小寫不敏感) |
| getRequestHeaderValuesMap() | Map<String, String[]> | 多值 Header,Value=字符串數組 |
代碼示例:遍歷所有請求參數
Map<String, String> paramMap = extCtx.getRequestParameterMap();
Iterator<String> names = extCtx.getRequestParameterNames();
while (names.hasNext()) {
String name = names.next();
System.out.println(name + " = " + paramMap.get(name));
}
代碼示例:獲取多值參數 (如 checkbox 群組)
String[] ids = extCtx.getRequestParameterValuesMap().get("id");
if (ids != null) for (String id : ids) System.out.println(id);
響應控制與重定向
redirect(String url):發送 302 重定向,自動處理 URL 編碼與 Session ID 重寫。
getResponseOutputStream() / getResponseOutputWriter():直接輸出二進制/文本 (如文件下載、圖片流)。
setResponseContentType(String)、setResponseContentLength(long)、addResponseCookie(Cookie)、setResponseHeader(String, String):精細控制響應。
資源與路徑處理
getResource(String path):返回 URL (如 /WEB-INF/faces-config.xml)。
getResourceAsStream(String path):返回 InputStream,讀取類路徑外資源。
getRealPath(String path):獲取服務器文件系統絕對路徑。
encodeResourceURL(String url)、encodeActionURL(String url):自動附加 Session ID (Cookie 不支援時)。
getRequestContextPath()、getRequestServletPath()、getRequestPathInfo():解析請求路徑組件。
用戶身份與安全
getUserPrincipal():返回 Principal (當前認證用戶)。
isUserInRole(String role):檢查角色授權。
getRemoteUser():獲取遠程用戶名。
getAuthType():認證類型 (BASIC/FORM/CLIENT-CERT/DIGEST)。
最佳實踐建議
- 優先使用 Map API 操作屬性,避免強轉原生對象,保持可移植性。
- Session 操作前檢查 Map 非空,防止 NPE。
- 請求參數讀取首選
getRequestParameterMap/ValuesMap,類型安全且支援多值。
- 重定向務必用
externalContext.redirect(),而非 HttpServletResponse.sendRedirect(),確保 JSF 狀態與 URL 重寫正確。
- 資源加載用
getResourceAsStream,勿假設文件系統路徑。