取得 Servlet 上下文的不同方法
1. 簡介
在使用 Java Servlet 建立 Web 應用程式時,我們經常需要在整個應用程式範圍內共享資訊或資源。我們可以透過存取ServletContext
物件來實現這一點。
在本教程中,我們將探索在 Servlet 中檢索ServletContext
不同方法。我們將實作一個簡單的 Servlet,並分析不同的方法,並證明它們都會傳回相同的共用物件。
2.什麼是ServletContext
?
我們先來解釋一下ServletContext
。它是一個接口,定義了一組 servlet 可以用來與 servlet 容器通訊的方法。
每個 Web 應用程式都有一個ServletContext
,容器在部署應用程式時會建立它。在非分散式環境中,同一應用程式內的所有 Servlet、過濾器和監聽器共用這個物件。而在分散式環境中,每個節點都有自己的ServletContext
。
3. 在 Servlet 內部存取ServletContext
現在讓我們實作一個簡單的 Servlet。我們還需要新增必要的依賴項並配置 Servlet 容器。完成這些設定後,我們可以使用@WebServlet
註解將 Servlet 對應到/context
URL:
@WebServlet("/context")
public class ContextServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
}
}
在doGet()
方法中,我們將示範檢索ServletContext
的不同方法。
3.1. 從 Servlet 直接訪問
存取ServletContext
最簡單的方法是直接在 servlet 實例上呼叫getServletContext()
方法:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
ServletContext contextFromServlet = this.getServletContext();
resp.getWriter()
.println("1) From HttpServlet: " + contextFromServlet);
}
為了驗證引用,我們可以使用HttpServletResponse
物件。呼叫getWriter()
會傳回一個PrintWriter
,我們可以用它將文字寫入回應主體,並將其顯示在瀏覽器或控制台中。如果我們執行應用程式並存取指定的 URL,則會顯示包含物件雜湊碼十六進位版本的輸出:
1) From HttpServlet: org.apache.catalina.core.ApplicationContextFacade@437620e9
Servlet 容器在初始化期間將ServletContext
注入到 Servlet 中。呼叫getServletContext()
即可取得該引用。這是在 Servlet 內部工作時最直接、最常用的方法。
3.2. 透過 ServletConfig 訪問
或者,我們可以透過 Servlet 設定物件存取ServletContext
容器在初始化期間會建立並使用ServletConfig
向 Servlet 傳遞訊息。我們可以先呼叫getServletConfig()
,然後再呼叫getServletContext()
來取得上下文:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
ServletConfig config = this.getServletConfig();
ServletContext contextFromConfig = config.getServletContext();
resp.getWriter()
.println("2) From ServletConfig: " + contextFromConfig);
}
讓我們檢查一下 servlet 產生了什麼:
2) From ServletConfig: org.apache.catalina.core.ApplicationContextFacade@437620e9
當我們已經在使用 Servlet 的設定時,這種方法很實用。如果我們需要在 Servlet 初始化期間與上下文進行交互,它也很有用。
3.3. 從請求中取得上下文
接下來,我們可以從HttpServletRequest
取得ServletContext
。從 Servlet 3.0 開始, HttpServletRequest
介面提供了專用的getServletContext()
方法:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
ServletContext contextFromRequest = req.getServletContext();
resp.getWriter()
.println("3) From HttpServletRequest: " + contextFromRequest);
}
這在輔助類別或過濾器中很有用,因為我們通常只能存取請求對象,而不是 Servlet 本身。與前面的方法類似,輸出顯示相同的物件:
3) From HttpServletRequest: org.apache.catalina.core.ApplicationContextFacade@437620e9
3.4. 透過 Session 物件檢索
最後,我們也可以透過HttpSession
物件存取ServletContext
。每個會話都與同一個應用程式上下文相關聯,因此在會話上呼叫getServletContext()
會傳回同一個實例:
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
ServletContext contextFromSession = req.getSession()
.getServletContext();
resp.getWriter()
.println("4) From HttpSession: " + contextFromSession);
}
雖然這種方法有效,但它比其他方法更間接,也不太常用。此外,如果 HTTP 會話物件不存在, getSession()
方法會隱式地建立它。不過,輸出結果確認,無論使用哪一種檢索方法, ServletContext
都是相同的:
4) From HttpSession: org.apache.catalina.core.ApplicationContextFacade@437620e9
4. 結論
在本文中,我們探討了在 Servlet 中取得ServletContext
的不同方法。我們可以透過HttpServlet
直接取得它,也可以透過ServletConfig
取得它,也可以透過HttpServletRequest
取得它,也可以透過HttpSession
間接取得它。
比較結果表明,所有這些方法都會傳回同一個ServletContext
實例,因為每個 Web 應用程式只有一個 ServletContext 實例。在 Servlet 內部工作時,最直接的方法是直接呼叫getServletContext()
。其他方法在我們可能已經處理配置、請求或會話物件的場景中很有用。
與往常一樣,完整的原始程式碼可在 GitHub 上取得。