通過用戶定義的屬性擴展標記的功能性Brett McLaughlin作者, O『Reilly and Associates2003 年 9 月 17 日BrettMcLaughlin 繼續他的 JSP 最佳實踐系列,這次他將用一個屬性來擴展自定義的時間戳標記( lastModified ),這個屬性讓頁面作者可以選擇他們自己的時間戳格式。上一期的 JSP 最佳實踐介紹了在JSP頁面中使用自定義標記庫的基礎知識。在那一期可以學到如何定義簡單的標記並通過標記庫描述符(tag library descriptor,TLD)讓其他 JSP 作者可以使用該標記。在這個星期,我們將以您已經知道的有關自定義標記的知識為基礎。我們上次採用的實例標記非常簡單,還存在一些不足之處。因此,現在我們將通過自定義屬性來擴展該標記的功能性。關於該實例的一點註解:本期的所有實例代碼都建立在上次我們開發的 lastModified 標記的基礎之上。如果您還沒有完整閱讀上一期,那麼在繼續閱讀本期之前您應該回頭閱讀一下上一期。JSP 標記最常見的需求就是能夠接受來自某個頁面(或者頁面作者)的數據,並響應該數據。標記 attributes 允許我們將這種功能性融入到自定義標記中。舉個非常簡單的例子,比如典型的「Hello, world」應用程序。很容易想像實現這一 scriptlet 的功能性的自定義標記是什麼樣子,但是,對這個標記作一點點擴展如何?在清單 1 中我們可以看到一個 JSP 頁面片段,其中有一個典型的「Hello, world!」標記,但是這個標記包括了一個名為 name 的屬性。

name 屬性為頁面作者將數據提供給 hello 標記創造了空間,在這個例子中,所提供的數據是一個人的名稱,應用程序將把它的消息轉播給這個人。實際上,我們已經自定義了「Hello, world」 ―― 但我們是怎樣進行定義的呢?清單 2 顯示了用於實現 hello 標記的 Java 代碼 :package com.ibm.examples;import java.io.IOException;import javax.servlet.jsp.*;import javax.servlet.jsp.tagext.*;public class HelloTag extends TagSupport { // The "person" to say hello to private String name; // Accept the attribute data public void setName(String name) { this.name = name; } public int doEndTag() { try { StringBuffer message = new StringBuffer("Hello, "); message.append(name) .append("!"); pageContext.getOut().println(message.toString()); } catch (IOException ignored) { } return EVAL_PAGE; }清單 2 中的代碼對於它所做的事情非常簡單。我們只是添加了一個 setXXX() 方法,其中 XXX 指的是該屬性的名稱,但正是由於這一添加,我們便已大大擴展了 hello 標記的功能性。現在,頁面作者可以為特定用途設置自定義數據,該數據可以根據需要進行保存、操縱或者激活。 doEndTag() 方法允許我們以任何方式使用標記數據。現在,讓討論更深入一點,看看當我們添加一個屬性到 lastModified 標記時會發生什麼情況。我們希望頁面作者能夠設置他們想要的輸出格式(最後修改數據),而不是只有一種顯示選擇。我們將從後端開始,首先擴展 lastModifiedTag 類, 使其包括一個 java.text.SimpleDateFormat 以用於輸出格式化,如清單 3 所示:package com.newInstance.site.tags;import java.io.File;import java.io.IOException;import java.text.DateFormat;import java.text.SimpleDateFormat;import java.util.Date;import javax.servlet.http.HttpServletRequest;import javax.servlet.jsp.tagext.TagSupport;public class LastModifiedTag extends TagSupport { private String format = "MMM d, yyyy"; public int doEndTag() { try { HttpServletRequest request = (HttpServletRequest)pageContext.getRequest(); String path = pageContext.getServletContext().getRealPath( request.getServletPath()); File file = new File(path); DateFormat formatter = new SimpleDateFormat(format); pageContext.getOut().println( formatter.format(new Date(file.lastModified()))); } catch (IOException ignored) { } return EVAL_PAGE; }}在清單 4 中,我們將新的格式化功能添加到 lastModified 標記中,這是通過添加一個屬性辦到的。注意, format 屬性的值與清單 3 中新引入的 format 方法變數是聯繫在一起的。package com.newInstance.site.tags;import java.io.File;import java.io.IOException;import java.text.DateFormat;import java.text.SimpleDateFormat;import java.util.Date;import javax.servlet.http.HttpServletRequest;import javax.servlet.jsp.tagext.TagSupport;public class LastModifiedTag extends TagSupport { private String format = "MMM d, yyyy"; public void setFormat(String format) { this.format = format; } public int doEndTag() { try { HttpServletRequest request = (HttpServletRequest)pageContext.getRequest(); String path = pageContext.getServletContext().getRealPath( request.getServletPath()); File file = new File(path); DateFormat formatter = new SimpleDateFormat(format); pageContext.getOut().println( formatter.format(new Date(file.lastModified()))); } catch (IOException ignored) { } return EVAL_PAGE; }}format 屬性允許頁面作者按照自己的喜好設置日期/時間的輸出格式。不過,在使用這個新屬性之前,我們必須在 TLD 文件(這個文件應該是 WEB-INF/tlds 目錄下的 site-utils.tld)中作一點修改,如清單 5 所示: 1.0 1.2 site-utils http://www.newInstance.com/taglibs/site-utils lastModified com.newInstance.site.tags.LastModifiedTag empty format 更新了 TLD 之後,我們應該可以開始使用新屬性了,那麼讓我們來測試一下吧。重新啟動 servlet 容器,以確保 servlet 容器接受了新的標記和 TLD 更改,然後連上帶有 lastModified 標記的頁面。千真萬確,時間戳出現了。但是我們可以看到,輸出的格式與之前沒什麼兩樣。問題就在於沒有添加新的 format 值,因此我們所看到的格式與老格式是一樣的。這個小測試展示了為 format 屬性添加默認值(在這個例子中,就是您馬上要看到的那個格式)的重要性。為自定義屬性添加一個默認值是一種很好的思想,因為這使得頁面作者在不想提供他們自己的值時可以省點力氣。在某些情況下,頁面作者可能會很高興使用默認值;在其他一些情況下,他們可能需要花點時間來了解新的屬性和格式,在這段時間內,暫時使用默認值是很有必要的。不管是哪種情況,通過為標記添加自定義屬性來創建選項,並為執行某種功能的頁面提供默認的行為,這樣做才是良好的編程習慣。當然,我們做這麼多事情並不是漫無目的的!清單 6 顯示了 footer.jsp ,這個文件來自原有的那個時間戳實例(參見 「The power of time stamps」 ),不過這裡為 format 屬性提供了一個值:

© 2003 Brett McLaughlin
Last Updated: format="HH:mm a zz :: MM/dd/yyyy"/>
雖然我們完成了一個良好的開端,但我們還只是簡要地描繪了關於處理自定義標記中的屬性的一些表面的東西。在下一期的 JSP 最佳實踐中,我們將討論一些更複雜的場景,這些場景都是您在創建自定義的、可擴展的時間戳標記時可能遇到的――例如錯誤處理和對不同時區的處理。同時,還將看到為不同類型的功能使用自定義屬性的實踐,到時候網上見。您可以參閱本文在 developerWorks 全球站點上的英文原文.還是JSP技術的初學者嗎?那麼請參見由 Brett McLaughlin 撰寫的 JSP最佳實踐系列前面的幾期。您或許還想研究一下對遵從JSP規範的IDE的使用。那麼下面有一些選擇:JEditNetBeansEclipseNoel Bergman 的 「JSP taglibs:設計帶來更好的可用性」( developerWorks, 2001年12月)介紹了自定義標記庫工具,這種工具允許創建JSTL。Jeff Wilson 的 「利用自定義標記控制您的 JSP 頁面」( developerWorks, 2002年1月)是關於自定義標記庫通信的入門讀物。「使用 JSP 和 JDBC 技術的動態的基於 Web 的數據訪問」(developerWorks, 2001年9月) 演示了對於訪問和操縱JSP頁面中內容必不可少的一些技術。Mark Kolb的 「JSTL 初級讀物」 (developerWorks, 2003年2月至5月)對 JSP 標準標記庫(JSP Standard Tag Library)作了完整的介紹。要獲得對JSP技術的指導性的介紹,請參見 Noel Bergman 的教程「JaveServer Pages 技術簡介」(developerWorks, 2001年8月)。要獲得JSP技術的細節,您最好的選擇是閱讀 JSP 規範說明書。Hans Bergsten 的JavaServer Pages (O『Reilly & Associates, 2002)是學習 JSP 技術時不可或缺的資料。參見developerWorks Java 技術教程頁面 以獲得完整的免費教程清單。在developerWorks Java 技術專區 您可以找到大量關於 Java 編程各個方面的文章(包括更多關於JSP技術的文章)。關於作者

Brett McLaughlin 自 Logo 時期(還記得那個小三角形嗎?)起就從事計算機方面的工作。目前,他專攻使用 Java 和 Java 相關的技術構建應用基礎設施。最近幾年,他一直在 Nextel Communications and Allegiance Telecom 公司,致力於實現這些基礎設施。Brett 是 Java Apache 項目 Turbine 的合創者之一,Turbine 為使用 Java servlets 的 Web 應用的開發構建了可重用組件基礎設施。對於EJBoss項目(一種開源 EJB 應用伺服器)和 Cocoon(一種開源 XML Web 發布引擎),他也作出了貢獻。您可以通過[email protected] 與 Contact Brett 聯繫。
推薦閱讀:

查看原文 >>
相关文章