J2EE探索者:隱式對象的多種用法
最後更新:2017-02-28
來源:互聯網
上載者:User
j2ee|對象 接著上月對會話範圍的介紹,企業 Java 專家 Kyle Gabhart 深入研究了 JSP 隱式對象的多種用法。接下來,他將介紹 9 個隱式對象,解釋每個對象的用途(或者多種用途),最後給出一些怎樣在 JSP 編程中使用這些便利工具的最佳實務。您可以到我們的 討論論壇 中分享您對這篇文章或者 J2EE 探索者 系列中的任何其他文章的想法。
本期的 J2EE探索者 是上個月的 正確處理會話範圍入門 的續篇。除了訪問會話範圍之外,JSP 隱式對象還可以用來處理 HTML 參數,轉寄請求到一個 Web 元件,包括組件的內容、通過 JSP 容器的日誌資料、控制輸出資料流,處理異常,等等。
本月,您將學到在 JSP 頁面中使用隱式對象。我們首先簡要概括 JSP 架構,其中包括了隱式對象。然後,我將介紹每個對象並描述它的核心功能。最後,我們將給出使用每種類型的對象和它提供的容器管理服務的一些最佳實務。
隱式對象簡介
JSP 架構背後的理念是提供一個 Web 元件,它允許開發人員著重關注 Web 內容的表示,而不用陷入解析、編程和資料操縱等細節。JSP 應用程式本質上是特殊的 Web 元件,在處理使用者請求之前,J2EE Web 容器首先將其轉換成 servlet。在每個 JSP 應用程式內部有一套完整的隱式對象。
隱式對象使得開發人員可以訪問容器提供的服務和資源。這些對象之所以定義為隱式的,是因為您不必顯式地聲明它們。不論您是否聲明它們——雖然您不能重複聲明它們,它們在每個 JSP 頁面當中都進行定義,並且在後台由容器使用。因為隱式對象是自動聲明的,所以我們只需要使用與一個給定對象相關的引用變數來調用其方法。
9 個隱式對象及其功能的簡單描述如下:
Application 是使用範圍最廣的上下文狀態。它允許 JSP 頁面的 servlet 與包括在同一應用程式中的任何 Web 元件共用資訊。
Config 允許將初始化資料傳遞給一個 JSP 頁面的 servlet。
Exceptioninclude 含有只能由指定的 JSP“error pages”訪問的異常資料。
Out 提供對 servlet 的輸出資料流的訪問。
Page 是JSP頁面的處理當前請求的 servlet 的執行個體。一般來說,JSP 頁面作者不使用該對象。
PageContext 是 JSP 頁面本身的上下文。它提供惟一一個 API 來管理具有不同範圍的屬性。這個 API 在實現 JSP 自訂標籤處理常式時使用得非常多。
Request 提供對 HTTP 要求資料的訪問,同時還提供用於加入特定於請求的資料的上下文。
Response 允許直接存取 HTTPServletResponse 對象,JSP 程式員很少使用該對象。
Session 可能是狀態管理上下文中使用得最多的對象。“會話”的概念是指單個使用者與 Web 應用程式在幾個請求上進行互動。
雖然有些隱式對象只提供單一的功能,但是幾個結合起來使用就可以提供多種功能。在接下來的一節裡,我們將按照功能分類來考察隱式對象:
會話管理:application, session, request, pageContext
流量控制:application, config, pageContext, request, session
日誌記錄和異常:application, config, exception, pageContext, request, session
輸入輸出控制:request, response, out
初始化參數:config
會話管理
上個月我們提到過,為 JSP 定義的四個隱式對象可以用來在一個特定的上下文或者範圍中加入有狀態資料。這四個對象是 application、session、request 和 pageContext。下表列出了這四個對象和它們定義的狀態上下文,同時還給出了對每個對象的簡單描述。
表1. JSP 狀態管理 隱式對象 範圍 描述
javax.servlet.ServletContext Application 代表整個運行時的 Web 模組(應用程式)。範圍為 application 的資料在同一個應用程式模組的所有 Web 元件之間共用。這很像J2EE 中提供的“全域(global)”資料
javax.servlet.http.HttpSession Session 代表當前的 HTTP 會話。除 page 範圍外,session 範圍是使用最普遍的上下文。這個對象在提供跨多個請求的持久的、有狀態的使用者體驗方面使用得最普遍
javax.servlet.http.HttpServletRequest Request 代表當前的 HTTP 要求。這個上下文可以跨越多個 Web 元件(servlet 和 JSP 頁面),只要這些組件屬於同一原子請求的一部分。由客戶機提供的特定於請求的資料(要求方法、URI、HTTP 參數等等)都被自動地儲存在一個request 上下文中。servlet 或 JSP 頁面還可以程式化地(programmatically)將資料的範圍指定為 request,以便允許同一 request 範圍中的其他 servlet 或 JSP 頁面可以擷取該資料
javax.servlet.jsp.PageContext Page 代表當前 JSP 頁面的上下文。因為一個 JSP 頁面的上下文包括當前的請求、會話和應用程式,所以使用pageContext 執行個體可以訪問與一個JSP 頁面相關的所有命名空間。它是所有對象的預設範圍,包括 JavaBeas 對象在內。 具有 page 範圍的對象通常會綁定到一個局部變數,以便在 scriptlet、運算式、JavaBeans 標記和自訂標籤中可以訪問它
從最佳實務的立場來看,我們應該儘可能地使用 page 範圍。它簡單,而且是 JSP 資料的預設範圍。request 範圍非常適合於運行期間在組件間共用資料以處理一個特定的請求。session 範圍被設計用來為單個使用者提供持久的、有狀態的體驗,它可以跨越多個請求。application 範圍只有需要在組件之間跨使用者會話共用資料時才應該使用。參閱參考資料以瞭解更多有關 session 範圍的資訊。
流量控制
物件導向設計方法的最大好處是可重用性。特別是,J2EE 系統將它們借用到模組化風格的開發中,其中組件可以在其他應用程式中重新安排、重新打包和重新使用。即使您對設計可重用的 Web 模組不感興趣,也很可能會發現您的 J2EE 應用程式由幾個部分組成。任何時候使用多個 servlet 或者 JSP 頁面(也就是組件)完成一個請求的時候,都需要使用某種類型的流量控制技術。Servlet 架構提供兩種這樣的技術:forward(轉寄) 和 include(包括)。
在 J2EE Web 開發中,forward 會把處理使用者請求的控制權轉交給到其他 Web 元件。forward 在有些時候會比較有用,比如說需要用一個組件設定一些 JavaBean、開啟或關閉資源、認證使用者,或者在將控制權傳遞給下一個組件之前需要執行一些準備工作。在轉寄之前可以執行很多類型的任務,但是要轉寄的組件不能設定回應標頭部資訊,也不能有內容發送到輸出緩衝區。所有與向客戶發送內容直接相關的任務必須由被轉寄的組件完成。
J2EE 中第二種流量控制技術是include。在使用 forward 時,要傳遞控制權。與此不同的是,執行 include 的組件維持對請求的控制權,而只是簡單地請求將另一個組件的輸出包括在該頁面的某個特定的地方。對於常見的設計項目,例如頁首、頁尾和導覽列等,這是一個非常好的方法。
forward 和 include 都是通過一個專門的對象 java.servlet.RequestDispatcher 來完成的。簡單地調用一個 ServletContext 對象的 getRequestDispatcher()方法就可以獲得一個RequestDispatcher 對象。得到對 ServletContext 對象的引用有幾種方法,我們可以:
使用隱式聲明的 application 變數,因為它的類型本身已經是 ServletContext。
調用方法 getServletContext(),該方法返回一個對隱式聲明的 application 變數的引用。
調用隱式聲明的 config 變數的 getServletContext()方法。
調用隱式聲明的 pageContext 變數的 getServletContext()方法。
調用隱式聲明的 request 變數的 getServletContext()方法。
調用隱式聲明的 session 變數的 getServletContext()方法。
清單1給出了使用隱式變數 application 的 forward 流量控制機制的程式碼範例。
清單1. forward 流量控制樣本
javax.servlet.RequestDispatcher rd;
/* Obtain a reference to a RequestDispatcher object via the implicit
application variable*/
rd = application.getRequestDispatcher( "/NextPage.jsp" );
/* Perform the forward specified by the RequestDispatcher
and pass along a reference to the current request and
response objects */
rd.forward( request, response );
清單2給出了同樣使用變數 application 的 include 流量控制的程式碼範例。
清單2. include 流量控制樣本
javax.servlet.RequestDispatcher rd;
/* Obtain a reference to a RequestDispatcher object via the implicit
application variable*/
rd = application.getRequestDispatcher( "/Header.jsp" );
/* Perform the include specified by the RequestDispatcher
and pass along a reference to the current request and
response objects */
rd.include( request, response );
forward 和 include 是添加到 J2EE Web 開發套件中的兩個非常棒的技術。還有其他一些方法可以在 JSP 頁面中完成 include,而且還有很多解決 J2EE 設計模式方面的文獻中講到了如何結合使用這兩種技術。參閱參考資料以瞭解更多資訊。
日誌記錄和異常
如果您需要把與 Web 應用程式相關的資訊儲存到一個日誌中,依然有內建的方法可用。ServletContext 介面聲明了兩個方法,用於把資料傳給一個日誌。其中一個方法接受簡單的簡訊:log( java.lang.String ),另一個方法接受一個異常資訊和一個簡訊:log(java.lang.Throwable, java.lang.String )。
在有了 ServletContext 介面提供的兩個可用的日誌記錄方法之後,剩下的關鍵是擷取一個對ServletContext 類型的對象的引用。像我們前面討論過的流量控制對象一樣,有多種方法可以擷取對 ServletContext 類型的對象的引用。在獲得了對象引用之後,簡單地調用 log()方法並向方法中傳遞必需的資料即可。一旦調用了這個方法,您當然就會希望能夠查看應用程式記錄檔以查看訊息。ServletContext 是一個簡單的介面,並且也沒有規定怎樣實現它聲明的方法。因而 log 方法的具體實現是由供應商處理的。他們可以把日誌資訊儲存到一個文字檔、二進位檔案、資料庫中,或者是供應商認為合適的其他格式中。您需要從伺服器的文檔中得知儲存日誌的位置。
雖然向一個記錄檔發送訊息相當有用,但是很多時候您可能還想在發生不可恢複的異常時顯示一個方便使用的錯誤訊息。要實現這一功能,您可以聲明,您的 JSP 頁面使用一個單獨的頁面來處理錯誤訊息。這是在 JSP 頁面的任何地方通過包含下面的 page 指令實現的:
<%@ page errorPage="ErrorMessage.jsp"%>
如果在處理 JSP 頁面時有一個異常拋出的話,exception 對象就會立即通過隱式聲明的 exception 變數的方式拋給指定的錯誤頁面。
為了使一個 JSP 頁面能夠作為一個錯誤頁面,它必須包含一個指令來聲明這個頁面是指定用來處理錯誤的特殊頁面,指令如下:
<%@ page isErrorPage="true"%>
為了使用 ErrorMessage.jsp 頁面能夠作為一個錯誤頁面,這個指令必須出現在頁面的某個地方。錯誤頁面可以顯示一個友好的資訊給使用者,然後可以將相關的異常資訊寫入日誌以供管理員日後查看。
輸入和輸出控制
因為 JSP 頁面僅僅是 HTTP servlet 的一個簡單抽象,所以您可以訪問 HttpServletRequest 和 HttpServletResponse 對象。如果需要特定於請求的資訊,比如客戶機瀏覽器的類型、HTTP post 的內容類型、客戶機效能、Cookie 資料或者請求參數,簡單地用隱式聲明的 request 變數直接調用適當的方法即可。類似地,如果您需要設定回應標頭部資訊,比如說瀏覽器類型、內容類型、內容長度等等,簡單地用隱式變數 response 調用適當的方法即可。
如果需要直接存取 JSP 頁面的輸出資料流,您可能會試圖通過隱式 response 變數調用 getWriter()或 getOutputStream()。然而由於 JSP 頁面的特殊性,您不能這樣做。如果需要直接存取輸出資料流,必須通過一個 avax.servlet.jsp.JSPWriter 類型的特殊緩衝 PrintWriter 對象來訪問。怎樣定位這樣一個對象的引用呢?JSP 容器將會為您隱式地聲明一個,並通過 out 變數提供給您。在 JSP scriptlet 中可以通過簡單地調用 out.print()或 out.println()使用它。
一般來說不需要像這樣直接使用 JSPWriter 對象,而只需簡單地把內容作為普通文本或者通過 JSP 運算式寫入,然後允許容器將這些資訊翻譯成 JSPWriter 調用。然而,在兩種情況下您需要直接使用 out 變數。一種情況是要為 JSP 自訂標籤定義處理常式,這部分內容我們將在下個月重點講到。另外一種情況是您想要對 JSP 建立的輸出擁有更多的控制。如果您有一段夾雜著 JSP scriptlets 和運算式的 HTML,您可能會發現建立大的 scriptlet 然後在需要輸出內容到客戶機的時候使用 out.println()語句這樣做會更簡潔、更容易。
初始化參數
如果您有一些待用資料想提供給 JSP 頁面使用,並且那些資料不會頻繁地改動,初始化參數可能會是一個比較好的選擇。初始化參數有時候又叫環境變數或者“init”參數,這些參數通過位於一個 per-servlet/JSP 內的 Web 應用程式的 web.xml 檔案指定,並且它們在servlet 的生命週期中唯讀取一次,即在初始化時讀取。
清單3是一個初始化參數聲明的例子。
清單3. 初始化參數聲明
<webapp>
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>com.gabhart.MyTestServlet</servlet-class>
<init-param>
<param-name>contactEmail</param-name>
<param-value>kyle@gabhart.com</param-value>
</init-param>
</servlet>
</webapp>
使用隱式變數 config 可以訪問這些參數的值,隱式變數 config 是對 JSP 頁面的ServletConfig 對象的引用。通過 ServletConfig 介面提供了兩個處理 init 參數的方法。可以根據名字對一個特定的參數完成一個尋找(getInitParameter( java.lang.String)), 或者也可以檢索到為 JSP 頁面定義的所有參數名字的一個 enumeration(getInitParameterNames())。在擁有了enumeration 之後,可以通過迴圈尋找每一個值。所有 init參數都是String 對象。如果需要其他的資料類型,比如說整數、浮點數或者布爾值,必須使用相應的封裝器類來解析字串。
結束語
JSP 技術提供了 Servlet 架構之上的一個非常有用的抽象,它讓 Web 設計者可以著重關注內容表示,而只要求知道較少的編程細節。在本文中,您已經看到了我們是如何使用隱式對象來快速、容易地開發 Web 應用程式的。
下個月,我們將開始講述 JSP 自訂標籤和 JSP 標準標記庫(JSTL)。學習自訂標籤如何促進表示和商務邏輯之間的分離,同時還讓您可以將動態資料合并到展示層。到那時,一起快樂地探索吧!
作者Blog:http://blog.csdn.net/zaowei21/
相關文章
淺析對政府資訊化建設認識的一些誤區
SOA:服務架構組件化
建造支撐系統的三大技術
企業級軟體的曆史與未來
教你在Java中實現3d編程簡介