kapok

          垃圾桶,嘿嘿,我藏的這么深你們還能找到啊,真牛!

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            455 隨筆 :: 0 文章 :: 76 評論 :: 0 Trackbacks
          http://www-900.ibm.com/developerWorks/cn/java/j-pj2ee7/index.shtml
          淺淡 JSP 技術(shù)中使用最多的對象

          級別:中級

          Kyle Gabhartkyle@gabhart.com
          顧問,Gabhart Consulting
          2003年 9 月

          Column icon接著上月對會話作用域的介紹,企業(yè) Java 專家 Kyle Gabhart 深入研究了 JSP 隱式對象的多種用法。接下來,他將介紹 9 個隱式對象,解釋每個對象的用途(或者多種用途),最后給出一些怎樣在 JSP 編程中使用這些便利工具的最佳實踐。您可以到我們的 討論論壇 中分享您對這篇文章或者 J2EE 探索者 系列中的任何其他文章的想法。

          本期的 J2EE探索者 是上個月的 正確處理會話作用域入門 的續(xù)篇。除了訪問會話作用域之外,JSP 隱式對象還可以用來處理 HTML 參數(shù),轉(zhuǎn)發(fā)請求到一個 Web 組件,包括組件的內(nèi)容、通過 JSP 容器的日志數(shù)據(jù)、控制輸出流,處理異常,等等。

          本月,您將學(xué)到在 JSP 頁面中使用隱式對象。我們首先簡要概括 JSP 架構(gòu),其中包括了隱式對象。然后,我將介紹每個對象并描述它的核心功能。最后,我們將給出使用每種類型的對象和它提供的容器管理服務(wù)的一些最佳實踐。

          隱式對象簡介
          JSP 架構(gòu)背后的理念是提供一個 Web 組件,它允許開發(fā)人員著重關(guān)注 Web 內(nèi)容的表示,而不用陷入解析、編程和數(shù)據(jù)操縱等細(xì)節(jié)。JSP 應(yīng)用程序本質(zhì)上是特殊的 Web 組件,在處理用戶請求之前,J2EE Web 容器首先將其轉(zhuǎn)換成 servlet。在每個 JSP 應(yīng)用程序內(nèi)部有一套完整的隱式對象。

          隱式對象使得開發(fā)人員可以訪問容器提供的服務(wù)和資源。這些對象之所以定義為隱式的,是因為您不必顯式地聲明它們。不論您是否聲明它們——雖然您不能重復(fù)聲明它們,它們在每個 JSP 頁面當(dāng)中都進(jìn)行定義,并且在后臺由容器使用。因為隱式對象是自動聲明的,所以我們只需要使用與一個給定對象相關(guān)的引用變量來調(diào)用其方法。

          9 個隱式對象及其功能的簡單描述如下:

          • Application 是使用范圍最廣的上下文狀態(tài)。它允許 JSP 頁面的 servlet 與包括在同一應(yīng)用程序中的任何 Web 組件共享信息。

          • Config 允許將初始化數(shù)據(jù)傳遞給一個 JSP 頁面的 servlet。

          • Exceptioninclude 含有只能由指定的 JSP“error pages”訪問的異常數(shù)據(jù)。

          • Out 提供對 servlet 的輸出流的訪問。

          • Page 是JSP頁面的處理當(dāng)前請求的 servlet 的實例。一般來說,JSP 頁面作者不使用該對象。

          • PageContext 是 JSP 頁面本身的上下文。它提供惟一一個 API 來管理具有不同作用域的屬性。這個 API 在實現(xiàn) JSP 自定義標(biāo)記處理程序時使用得非常多。

          • Request 提供對 HTTP 請求數(shù)據(jù)的訪問,同時還提供用于加入特定于請求的數(shù)據(jù)的上下文。

          • Response 允許直接訪問 HTTPServletResponse 對象,JSP 程序員很少使用該對象。

          • Session 可能是狀態(tài)管理上下文中使用得最多的對象。“會話”的概念是指單個用戶與 Web 應(yīng)用程序在幾個請求上進(jìn)行交互。

          雖然有些隱式對象只提供單一的功能,但是幾個結(jié)合起來使用就可以提供多種功能。在接下來的一節(jié)里,我們將按照功能分類來考察隱式對象:

          • 會話管理:application, session, request, pageContext
          • 流控制application, config, pageContext, request, session
          • 日志記錄和異常application, config, exception, pageContext, request, session
          • 輸入/輸出控制request, response, out
          • 初始化參數(shù):config

          會話管理
          上個月我們提到過,為 JSP 定義的四個隱式對象可以用來在一個特定的上下文或者作用域中加入有狀態(tài)數(shù)據(jù)。這四個對象是 applicationsessionrequest pageContext。下表列出了這四個對象和它們定義的狀態(tài)上下文,同時還給出了對每個對象的簡單描述。

          表1. JSP 狀態(tài)管理
          隱式對象 作用域 描述
          javax.servlet.ServletContext Application 代表整個運行時的 Web 模塊(應(yīng)用程序)。作用域為 application 的數(shù)據(jù)在同一個應(yīng)用程序模塊的所有 Web 組件之間共享。這很像J2EE 中提供的“全局(global)”數(shù)據(jù)
          javax.servlet.http.HttpSession Session 代表當(dāng)前的 HTTP 會話。除 page 作用域外,session 作用域是使用最普遍的上下文。這個對象在提供跨多個請求的持久的、有狀態(tài)的用戶體驗方面使用得最普遍
          javax.servlet.http.HttpServletRequest Request 代表當(dāng)前的 HTTP 請求。這個上下文可以跨越多個 Web 組件(servlet 和 JSP 頁面),只要這些組件屬于同一原子請求的一部分。由客戶機提供的特定于請求的數(shù)據(jù)(請求方法、URI、HTTP 參數(shù)等等)都被自動地保存在一個request 上下文中。servlet 或 JSP 頁面還可以程式化地(programmatically)將數(shù)據(jù)的作用域指定為 request,以便允許同一 request 作用域中的其他 servlet 或 JSP 頁面可以獲取該數(shù)據(jù)
          javax.servlet.jsp.PageContext Page 代表當(dāng)前 JSP 頁面的上下文。因為一個 JSP 頁面的上下文包括當(dāng)前的請求、會話和應(yīng)用程序,所以使用pageContext 實例可以訪問與一個JSP 頁面相關(guān)的所有命名空間。它是所有對象的默認(rèn)作用域,包括 JavaBeas 對象在內(nèi)。 具有 page 作用域的對象通常會綁定到一個局部變量,以便在 scriptlet、表達(dá)式、JavaBeans 標(biāo)記和自定義標(biāo)記中可以訪問它

          從最佳實踐的立場來看,我們應(yīng)該盡可能地使用 page 作用域。它簡單,而且是 JSP 數(shù)據(jù)的默認(rèn)作用域。request 作用域非常適合于運行期間在組件間共享數(shù)據(jù)以處理一個特定的請求。session 作用域被設(shè)計用來為單個用戶提供持久的、有狀態(tài)的體驗,它可以跨越多個請求。application 作用域只有需要在組件之間跨用戶會話共享數(shù)據(jù)時才應(yīng)該使用。參閱參考資料以了解更多有關(guān) session 作用域的信息。

          流控制
          面向?qū)ο笤O(shè)計方法的最大好處是可重用性。特別是,J2EE 系統(tǒng)將它們借用到模塊化風(fēng)格的開發(fā)中,其中組件可以在其他應(yīng)用程序中重新安排、重新打包和重新使用。即使您對設(shè)計可重用的 Web 模塊不感興趣,也很可能會發(fā)現(xiàn)您的 J2EE 應(yīng)用程序由幾個部分組成。任何時候使用多個 servlet 或者 JSP 頁面(也就是組件)完成一個請求的時候,都需要使用某種類型的流控制技術(shù)。Servlet 架構(gòu)提供兩種這樣的技術(shù):forward(轉(zhuǎn)發(fā)) 和 include(包括)。

          在 J2EE Web 開發(fā)中,forward 會把處理用戶請求的控制權(quán)轉(zhuǎn)交給到其他 Web 組件。forward 在有些時候會比較有用,比如說需要用一個組件設(shè)置一些 JavaBean、打開或關(guān)閉資源、認(rèn)證用戶,或者在將控制權(quán)傳遞給下一個組件之前需要執(zhí)行一些準(zhǔn)備工作。在轉(zhuǎn)發(fā)之前可以執(zhí)行很多類型的任務(wù),但是要轉(zhuǎn)發(fā)的組件不能設(shè)置響應(yīng)頭部信息,也不能有內(nèi)容發(fā)送到輸出緩沖區(qū)。所有與向客戶發(fā)送內(nèi)容直接相關(guān)的任務(wù)必須由被轉(zhuǎn)發(fā)的組件完成。

          J2EE 中第二種流控制技術(shù)是include。在使用 forward 時,要傳遞控制權(quán)。與此不同的是,執(zhí)行 include 的組件維持對請求的控制權(quán),而只是簡單地請求將另一個組件的輸出包括在該頁面的某個特定的地方。對于常見的設(shè)計元素,例如頁首、頁腳和導(dǎo)航欄等,這是一個非常好的方法。

          forward 和 include 都是通過一個專門的對象 java.servlet.RequestDispatcher 來完成的。簡單地調(diào)用一個 ServletContext 對象的 getRequestDispatcher()方法就可以獲得一個RequestDispatcher 對象。得到對 ServletContext 對象的引用有幾種方法,我們可以:

          • 使用隱式聲明的 application 變量,因為它的類型本身已經(jīng)是 ServletContext。
          • 調(diào)用方法 getServletContext(),該方法返回一個對隱式聲明的 application 變量的引用。
          • 調(diào)用隱式聲明的 config 變量的 getServletContext()方法
          • 調(diào)用隱式聲明的 pageContext 變量的 getServletContext()方法
          • 調(diào)用隱式聲明的 request 變量的 getServletContext()方法
          • 調(diào)用隱式聲明的 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 開發(fā)工具包中的兩個非常棒的技術(shù)。還有其他一些方法可以在 JSP 頁面中完成 include,而且還有很多解決 J2EE 設(shè)計模式方面的文獻(xiàn)中講到了如何結(jié)合使用這兩種技術(shù)。參閱參考資料以了解更多信息。

          日志記錄和異常
          如果您需要把與 Web 應(yīng)用程序相關(guān)的信息存儲到一個日志中,依然有內(nèi)建的方法可用。ServletContext 接口聲明了兩個方法,用于把數(shù)據(jù)傳給一個日志。其中一個方法接受簡單的文本消息:log( java.lang.String ),另一個方法接受一個異常信息和一個文本消息:log(java.lang.Throwable, java.lang.String )

          在有了 ServletContext 接口提供的兩個可用的日志記錄方法之后,剩下的關(guān)鍵是獲取一個對ServletContext 類型的對象的引用。像我們前面討論過的流控制對象一樣,有多種方法可以獲取對 ServletContext 類型的對象的引用。在獲得了對象引用之后,簡單地調(diào)用 log()方法并向方法中傳遞必需的數(shù)據(jù)即可。一旦調(diào)用了這個方法,您當(dāng)然就會希望能夠查看應(yīng)用程序日志以查看消息。ServletContext 是一個簡單的接口,并且也沒有規(guī)定怎樣實現(xiàn)它聲明的方法。因而 log 方法的具體實現(xiàn)是由供應(yīng)商處理的。他們可以把日志信息存儲到一個文本文件、二進(jìn)制文件、數(shù)據(jù)庫中,或者是供應(yīng)商認(rèn)為合適的其他格式中。您需要從服務(wù)器的文檔中得知存儲日志的位置。

          雖然向一個日志文件發(fā)送消息相當(dāng)有用,但是很多時候您可能還想在發(fā)生不可恢復(fù)的異常時顯示一個用戶友好的錯誤消息。要實現(xiàn)這一功能,您可以聲明,您的 JSP 頁面使用一個單獨的頁面來處理錯誤消息。這是在 JSP 頁面的任何地方通過包含下面的 page 指令實現(xiàn)的:

          
          <%@ page errorPage="ErrorMessage.jsp"%>
          

          如果在處理 JSP 頁面時有一個異常拋出的話,exception 對象就會立即通過隱式聲明的 exception 變量的方式拋給指定的錯誤頁面。

          為了使一個 JSP 頁面能夠作為一個錯誤頁面,它必須包含一個指令來聲明這個頁面是指定用來處理錯誤的特殊頁面,指令如下:

          
          <%@ page isErrorPage="true"%>
          

          為了使用 ErrorMessage.jsp 頁面能夠作為一個錯誤頁面,這個指令必須出現(xiàn)在頁面的某個地方。錯誤頁面可以顯示一個友好的信息給用戶,然后可以將相關(guān)的異常信息寫入日志以供管理員日后查看。

          輸入和輸出控制
          因為 JSP 頁面僅僅是 HTTP servlet 的一個簡單抽象,所以您可以訪問 HttpServletRequest HttpServletResponse 對象。如果需要特定于請求的信息,比如客戶機瀏覽器的類型、HTTP post 的內(nèi)容類型、客戶機性能、Cookie 數(shù)據(jù)或者請求參數(shù),簡單地用隱式聲明的 request 變量直接調(diào)用適當(dāng)?shù)姆椒纯伞n愃频兀绻枰O(shè)置響應(yīng)頭部信息,比如說瀏覽器類型、內(nèi)容類型、內(nèi)容長度等等,簡單地用隱式變量 response 調(diào)用適當(dāng)?shù)姆椒纯伞?

          如果需要直接訪問 JSP 頁面的輸出流,您可能會試圖通過隱式 response 變量調(diào)用 getWriter()getOutputStream()。然而由于 JSP 頁面的特殊性,您不能這樣做。如果需要直接訪問輸出流,必須通過一個 avax.servlet.jsp.JSPWriter 類型的特殊緩沖 PrintWriter 對象來訪問。怎樣定位這樣一個對象的引用呢?JSP 容器將會為您隱式地聲明一個,并通過 out 變量提供給您。在 JSP scriptlet 中可以通過簡單地調(diào)用 out.print()out.println()使用它。

          一般來說不需要像這樣直接使用 JSPWriter 對象,而只需簡單地把內(nèi)容作為普通文本或者通過 JSP 表達(dá)式寫入,然后允許容器將這些信息翻譯成 JSPWriter 調(diào)用。然而,在兩種情況下您需要直接使用 out 變量。一種情況是要為 JSP 自定義標(biāo)記定義處理程序,這部分內(nèi)容我們將在下個月重點講到。另外一種情況是您想要對 JSP 創(chuàng)建的輸出擁有更多的控制。如果您有一段夾雜著 JSP scriptlets 和表達(dá)式的 HTML,您可能會發(fā)現(xiàn)創(chuàng)建大的 scriptlet 然后在需要輸出內(nèi)容到客戶機的時候使用 out.println()語句這樣做會更簡潔、更容易。

          初始化參數(shù)
          如果您有一些靜態(tài)數(shù)據(jù)想提供給 JSP 頁面使用,并且那些數(shù)據(jù)不會頻繁地改動,初始化參數(shù)可能會是一個比較好的選擇。初始化參數(shù)有時候又叫環(huán)境變量或者“init”參數(shù),這些參數(shù)通過位于一個 per-servlet/JSP 內(nèi)的 Web 應(yīng)用程序的 web.xml 文件指定,并且它們在servlet 的生命周期中只讀取一次,即在初始化時讀取。

          清單3是一個初始化參數(shù)聲明的例子。

          清單3. 初始化參數(shù)聲明
          
          <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 可以訪問這些參數(shù)的值,隱式變量 config 是對 JSP 頁面的ServletConfig 對象的引用。通過 ServletConfig 接口提供了兩個處理 init 參數(shù)的方法。可以根據(jù)名字對一個特定的參數(shù)完成一個查找(getInitParameter( java.lang.String)), 或者也可以檢索到為 JSP 頁面定義的所有參數(shù)名字的一個 enumeration(getInitParameterNames())。在擁有了enumeration 之后,可以通過循環(huán)查找每一個值。所有 init參數(shù)都是String 對象。如果需要其他的數(shù)據(jù)類型,比如說整數(shù)、浮點數(shù)或者布爾值,必須使用相應(yīng)的包裝器類來解析字符串。

          結(jié)束語
          JSP 技術(shù)提供了 Servlet 架構(gòu)之上的一個非常有用的抽象,它讓 Web 設(shè)計者可以著重關(guān)注內(nèi)容表示,而只要求知道較少的編程細(xì)節(jié)。在本文中,您已經(jīng)看到了我們是如何使用隱式對象來快速、容易地開發(fā) Web 應(yīng)用程序的。

          下個月,我們將開始講述 JSP 自定義標(biāo)記和 JSP 標(biāo)準(zhǔn)標(biāo)記庫(JSTL)。學(xué)習(xí)自定義標(biāo)記如何促進(jìn)表示和業(yè)務(wù)邏輯之間的分離,同時還讓您可以將動態(tài)數(shù)據(jù)合并到表示層。到那時,一起快樂地探索吧!

          參考資料

          關(guān)于作者
          Photo of Kyle GabhartKyle Gabhart 是 J2EE、XML 和 Web 服務(wù)技術(shù)方面的獨立顧問和專家。Kyle 是一位很受歡迎的公眾演講者,以其對新技術(shù)的熱情、生動的分析和陳述而聞名。要獲取他最近以及即將舉行的演講或者業(yè)內(nèi)出版物的信息,請訪問 Gabhart.com。您也可以通過 kyle@gabhart.com 與 Kyle 聯(lián)系。
          posted on 2005-04-08 14:38 笨笨 閱讀(321) 評論(0)  編輯  收藏 所屬分類: J2EEALL
          主站蜘蛛池模板: 江安县| 文安县| 云安县| 大姚县| 靖边县| 民县| 遂昌县| 鸡东县| 长岭县| 遂平县| 河北区| 南皮县| 寿阳县| 惠安县| 东莞市| 汽车| 吉隆县| 台湾省| 南宁市| 嘉义市| 鲁甸县| 图木舒克市| 汉寿县| 诸城市| 永吉县| 阜康市| 社旗县| 图木舒克市| 和平县| 建瓯市| 仁怀市| 五大连池市| 泾川县| 东乡县| 宁强县| 军事| 梅河口市| 宁阳县| 从江县| 马尔康县| 特克斯县|