<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-208  評論-469  文章-30  trackbacks-0
    XML和JSP是這些日子中最熱的東西。本文介紹如何聯合這兩種技術來建設動態網站。你還可以同時看一下DOM,XPath,XSL,和其它Java-XML技術的示例代碼。
    我們在此假設你已經了解JavaServer Pages(JSP)和Extensible Markup Language (XML)。但也許你對該如何綜合使用它們仍然有些迷惑。
    JSP的應用很容易,你可以用它設計網頁,使之看起來似乎和HTML一樣。唯一的不同是JSP是動態執行的。例如,它們可以處理表單form和讀寫數據庫。
    XML的應用的說明則比較困難。似乎所有的產品都支持它,每個人也好象都以各種不同目的在使用它。
    在本文中,你可以看到如何使用一種相當先進的方式用XML來設計一個系統。許多站點有巨量數據收集并以一種很標準或很不標準的方式來顯示它們。我將設計一個系統,它使用XML文件在web服務器上進行存儲,并用JSP來顯示數據。
    XML vs 關系型數據庫

    "等一下!"你可能問,"你用XML文件存儲數據嗎?為什么不使用數據庫?"
    這個問題問的很好。我的回答是,對很多目的用途來說,用數據庫太過浪費了。.要使用一個數據庫,你必須安裝和支持一個分離的服務器處理進程(a separate server process),它常要求有安裝和支持它的administrator。你必須學習SQL, 并用SQL寫查詢,然后轉換數據,再返回。而如果你用XML文件存儲數據,將可減少額外的服務器的負荷。還有,你還找到了一個編輯數據的簡單方法。你只要使用文本編輯器,而不必使用復雜的數據庫工具。XML文件很容易備份,和朋友共享,或下載到你的客戶端。同樣的,你可以方便地通過ftp上載新的數據到你的站點。
    XML還有一個更抽象的優點,即作為層次型的格式比關系型的更好。它可以用一種很直接的方式來設計數據結構來符合你的需要。你不需要使用一個實體-關系編輯器,也不需要使你的圖表(schema)標準化。如果你有一個元素(element)包含了另一個元素,你可以直接在格式中表示它,而不需要使用表的關聯。
    注意,在很多應用中,依靠文件系統是不夠充分的。如果更新很多,文件系統會因為同時寫入而受到破壞。數據庫則通常支持事務處理,可以應付所發生的請求而不至于損壞。對于復雜的查詢統計要有反復、及時的更新,此時數據庫表現都很優秀。當然,關系型數據庫還有很多優點,包括豐富的查詢語言,圖表化工具,可伸縮性,存取控制等等。
    (注意:你可以使用簡單的文件鎖定來提供一個事務處理服務器,你還可以在java中執行一種 XML index-and-search工具,不過這已經是另外一篇文章的主題了。)
    在下面這樣的案例中,正如大多數中小規模的、基于發布信息的站點一樣,你可能涉及的大多數數據存取都是讀,而不是寫,數據雖然可能很大,但相對來說并沒有經常的更新變化,你也不需要做很復雜的查詢,即使你需要做,也將用一個獨立的查詢工具,那么成熟的RDBMS的優點消失了,而面向對象型的數據模型的優點則可以得到體現。
    最后,為你的數據庫提供一個查詢器外殼來進行SQL查詢并將他們轉化進入XML stream也是完全有可能的。
    所以你可以選擇這二種方式之一。XML正變成一種非常健壯的,便于編程的工具,作為某個成熟的數據庫的前端工具來進行存儲和查詢。(Oracle的XSQL servlet即是這種技術的一個很好的例子。)
    應用篇:一個在線相冊

    所有人都喜歡照相!他們喜歡展示自己的,親人的,朋友的,度假時的照片,而 Web 是他們展示的好地方。-- 即使千里之外的親戚都可以看到。我將著重于定義一個單獨的Picture對象。(這一應用的源代碼在Resources中可以取得) 。該對象描述了表示一張照片所需要的字段:title,date,一個可選的標題,以及對圖片來源的一個指向。
    一個圖象,需要它自己的一些字段:源文件( GIF/JPEG)的定位,寬度和高度像素(以協助建立標記。這里可以看到一個很簡單的優點,即使用文件系統來代替數據庫的時候,你可以將圖形文件存放在與數據文件相同的目錄中。
    最后,讓我們來用一個元素擴展圖片記錄,該元素定義了一套縮略圖(thumbnail)來用于內容表或其它地方。這里我用了和先前同樣定義的圖片內容。
    一張圖片的XML表示可以是這樣的:
    <picture>
    <title>Alex On The Beach</title>
    <date>1999-08-08</date>
    <caption>Trying in vain to get a tan</caption>
    <image>
    <src>alex-beach.jpg</src>
    <width>340</width>
    <height>200</height>
    </image>
    <thumbnails>
    <image>
    <src>alex-beach-sm.jpg</src>
    <width>72</width>
    <height>72</height>
    </image>
    <image>
    <src>alex-beach-med.jpg</src>
    <width>150</width>
    <height>99</height>
    </image>
    </thumbnails>
    </picture>

    注意,通過使用XML, 你將一張單獨圖片的全部信息放到了一個單獨的文件中,而不是將它分散放入3-4個表中。
    我們將這稱為 .pix file
    -- 于是你的文件系統會是這樣的:
    summer99/alex-beach.pix
    summer99/alex-beach.jpg
    summer99/alex-beach-sm.jpg
    summer99/alex-beach-med.jpg
    summer99/alex-snorkeling.pix
    etc.
    技術篇
    俗話說,要剝下貓的皮的方法何止一種。同樣,將XML數據放到JSP中也不止一種辦法。這里列舉了其中一些方法,(其實,很多其它工具也可以做得同樣出色。)
    DOM: 你可以使用類(classes)來調用DOM接口(interface)對XML文件進行分析檢查。
    XMLEntryList: 你可以使用我的代碼來將XML加載到name-value pairs 的java.util.List中。
    XPath: 你可以使用一個 XPath處理器(如Resin)通過路徑名在XML文件中定位元素。
    XSL:你可以使用某種XSL處理器將XML轉換成為HTML。
    Cocoon: 你可以使用開放源碼的Cocoon framework
    運行你自己的bean: 你可以寫一個外殼類(wrapper class),使用某種其它技術來將數據加載到字定義的JavaBean中。

    請注意這些技術將和一個你從另外來源取得的XML stream執行得同樣出色,例如一個客戶端或者一個應用服務器。
    JavaServer Pages

    JSP規范有很多替身,不同的JSP產品表現也不盡相同,不同版本之間也有差別。我選擇了Tomcat,這基于以下原因:
    它支持大多數最新的JSP/servlet規范
    它受到 Sun和Apache認同
    你可以獨立運行它而不需要另外配置一個Web服務器。
    它是開放源碼的
    你可以選擇任何你喜歡的JSP引擎,但要自己配置它,它必須至少支持JSP 1.0規范。0.91和1.0之間有了許多區別。而JSWDK (Java Server Web Development Kit) 可能剛剛好地適合要求。
    JSP結構
    當創建一個jsp網站 (Webapp), 我喜歡將公用的函數、導入、常量、變量聲明都放入到一個單獨的文件init.jsp中。然后用 <%@include file="init.jsp"%>加載到每一個文件中去。 <%@include%> 就象C語言的 #include, include在編譯時使其中的文本作為一個部分被加入并一起進行編譯,相對地, <jsp:include>標記則是使其中的文件被獨立地進行編譯,然后在文件中嵌入一個對它的調用。
    查找文件
    當JSP啟動時,初始化后第一件事情就是查找你要的XML文件。它是怎么知道在眾多文件中你要找的是哪一個? 它來自與一個參數,使用者會在調用jsp的URL中加入參數: picture.jsp?file=summer99/alex-beach.pix (或者通過HTML表單來傳遞文件參數)。
    但是,當JSP接受此參數以后,你仍然只完成了一半工作,因為還要知道文件系統的根目錄在哪里。例如,在Unix系統中,實際文件可能在這樣的路徑:
    /home/alex/public_html/pictures/summer99/alex-beach.pix。
    JSP文件在執行狀態時沒有當前路徑概念。所以你為java.io包要給出一個絕對路徑。
    Servlet API可以提供一個方法來將一個URL路徑,從相對于當前JSP或Servlet的路徑轉化成為一個絕對的文件系統路徑。方法是:
    ServletContext.getRealPath(String)。
    每一個JSP有一個叫做application的 ServletContext對象。所以代碼可以是:
    String picturefile =
    application.getRealPath("/" + request.getParameter("file"));
    或者
    String picturefile =
    getServletContext().getRealPath("/" + request.getParameter("file"));
    它也可以在servlet中工作。(你必須加上 / 因為此方法需要傳遞request.getPathInfo()的結果。)
    這里有一個重要的提示:每當你存取本地的資源,要非常小心地檢查輸入數據的合法性。黑客或者粗心的用戶,可能發送偽造的或錯誤的數據來破壞你的站點。例如,請想一下以下的表達會發生什么結果:
    如果輸入了file=../../../../etc/passwd。這樣用戶回讀到你的服務器的password文件!

    DOM (Document Object Model)

    DOM 代表文檔對象模型Document Object Model。它是瀏覽XML文檔的一種標準API,由World Wide Web Consortium (W3C)發展。 接口在org.w3c.dom包中,文檔參見W3C站點。
    有許多可用的DOM分析器工具。我選擇了 IBM的XML4J。但你可以使用任何其它的DOM分析器。這是因為DOM是一套接口,而不是類 --所有的DOM分析器(parser)必須返回同樣地處理這些接口的對象。

    遺憾的是,雖然很標準,DOM還是有兩大缺陷:
    1 API雖然也是面向對象的,還是相當笨重。
    DOM parser并沒有標準的API,所以,當每一個分析器返回一個org.w3c.dom對象,文檔對象--分析器初始化和文件自身加載的方式,對應于不同分析器通常總是特定的。
    這個簡單的上面已描述的圖片文件在DOM中可以在一個樹結構中通過一些對象表示如下:
    Document Node
    --> Element Node "picture"
    --> Text Node "\n " (whitespace)
    --> Element Node "title"
    --> Text Node "Alex On The Beach"
    --> Element Node "date"
    --> ... etc.
    為了取得“Alex On The Beach”,你要做一些方法調用,游歷DOM樹,而且,分析器可能選擇分散“whitespace”文本nodes的一些數據,你不得不使用循環和串聯等(你可以通過調用normalize()來糾正這個問題。)分析器可能還包含了分離的XML實體(如 &), CDATA nodes或者其它實體nodes (如big會被變成至少三個node。也沒有辦法在DOM中簡單表示"get me the text value of the title element." 總之,在DOM中游歷有一點笨重。(參見本文用XPath取代DOM章節。)
    2 從更高處看,DOM的問題是XML對象無法象Java對象一樣可以直接得到,它們需要通過 DOM API一個一個地得到。
    你可以參考我的為Java-XML Data Binding技術討論做的一些歸納,那里也用了這種直接使用Java的方法來存取XML數據。
    我寫了一個小的工具類,叫做DOMUtils,包含了靜態方法來執行公用的DOM任務。例如,要獲得根(圖片)元素的title子元素的文本內容,你可以編寫如下代碼:
    Document doc = DOMUtils.xml4jParse(picturefile);
    Element nodeRoot = doc.getDocumentElement();
    Node nodeTitle = DOMUtils.getChild(nodeRoot, "title");
    String title = (nodeTitle == null) ? null : DOMUtils.getTextValue(nodeTitle);

    得到image子元素的值也同樣直接:
    Node nodeImage = DOMUtils.getChild(nodeRoot, "image");
    Node nodeSrc = DOMUtils.getChild(nodeImage, "src");
    String src = DOMUtils.getTextValue(nodeSrc);
    等等。
    一旦你需要將Java變量用于每一個相關的元素,你必須做的是將變量嵌入到 HTML 標記中去:
    <table bgcolor="#FFFFFF" border="0" cellspacing="0" cellpadding="5">
    <tr>
    <td align="center" valign="center">
    <img src="<%=src%>" width="<%=width%>" height="<%=height%>" border="0" alt="<%=src%>"></td>
    </tr>
    </table>

    用JSP bean進行model/view分離

    所有上面的picture-dom.jsp代碼是很不吸引人的。雖然你可以在jsp中加入上萬條java代碼,但這樣就沒有使用JSP JavaBeans方法看上去來得簡單。javabean存放了大量Java代碼,并在JSP腳本中加以調用。
    為了制作一個模型,將所有java代碼放在JSP中來開始一個項目,這樣相對比較簡單。一旦有什么新的想法可以直接回去展開代碼,然后改寫為一些JavaBeans。雖然投資較高,但長遠來看回報更好,因為你的應用更為模型化。你可以在多個頁面中重復使用bean而不用擔心剪貼帶來的不良后果。
    在我們的案例中,一個典型的JSP JavaBean是從XML中展開字符串。你可以定義Picture, Image和Thumbnails類,來表示主要的XML文件中的元素。這些beans帶有構造器constructors或者setter方法,它們從展開值中帶入一個DOM node或一個文件名。你可以參考picturebeans包或picture-beans.jsp.
    在看代碼時請注意以下幾點:
    * 我將接口的定義獨立于類的執行,這樣你可以很自由地選擇在將來進行替代,你可以將值存放在一個List中,或者在DOM自身,甚至可以在數據庫中。

    * bean在一個自定義的包中被定義--picturebeans。所有JSP bean必須要在某一個包中。大多數JSP引擎都不能從缺省包中發現類。

    * 除了get方法,我也提供了set方法,當前你只是讀取,但在將來,你要讓用戶編輯圖片,所以你要規劃用語修改寫入屬性的功能。
    * <%=picture.getCaption()%>取代了 <%=caption%>, 因為值是存放在一個bean中而不是本地變量中。但是,如果你需要,你可以將本地變量定義為
    String caption = picture.getCaption(); 這也是允許的,這可以使代碼更容易閱讀和理解。
     
    * 通過thumbnails放大縮小
    你可能已經注意到我的第一個的 JSP的輸出, picture-dom.html,使用了全部大小的源圖片文件。我們可以稍微修改一下代碼,使它顯示一個縮略圖,我將把縮略圖列表存放在XML數據文件中。
    讓我們定義一個參數,zoom,它的值決定了要顯示哪一個縮略圖。點擊這個縮略圖后回顯示全部大小的圖片;點擊Zoom In或Zoom Out按鈕將選擇列表中下/上一種縮略圖。

    * 由于縮略圖對象返回一個Image對象的java.util.List,所以要找到正確的縮略圖并不容易,如果用(Image)picture.getThumbnails().get(i)的話。

    * 要制作Zoom In和 Zoom Out連接,你必須建立一個對同一頁面的遞歸的引用,但使用不同的參數。為了做到這一點,你要使用request.getRequestURI()方法。這只為你提供了該servlet的路徑,沒有參數,所以你可以在此補上你要的參數。
    <%
    if (zoom < (thumbnails.size() -1)) {
    out.print("<a href=\" +
    request.getRequestURI() +
    "?file=" + request.getParameter("file") +
    "&zoom=" + (zoom+1) +
    ">");
    out.print("Zoom In");
    }
    %>
    這里是一個HTML的屏幕拷貝。

    http://www.javaworld.com/jw-03-2000/jspxml/picture-dom.html

    使用JSP bean

    JSP規范定義了 <jsp:useBean>標記來自動實例化和使用JavaBeans。useBean標記可以總是被嵌入的Java代碼取代,這里我也是這么做的。也是由于這樣的原因,人們有時質問使用 useBean 和setProperty標記還有什么必要。這種做法的優點是:

    標記語法有利于HTML設計者獨立工作。
    useBean有一個scope參數,可以自動地決定bean是否必須存儲為一個本地變量,一個 session變量或一個application屬性。
    如果這個變量是持久的(session或application),useBean必要時可以將它初始化,并切在它確實存在的時候才去取得變量。
    長遠看標記對今后的JSP規范版本來說更為便攜(portable)或者更改執行(例如,, 一個假定的JSP引擎在一個數據庫中存儲了變量,或者跨服務器共享數據。)
    這個應用中對應的useBean語句為:
    <jsp:useBean id="picture" scope="request" class="picturebeans.DOMPicture">
    <%
    Document doc = DOMUtils.xml4jParse(picturefile);
    Element nodeRoot = doc.getDocumentElement();
    nodeRoot.normalize();
    picture.setNode(nodeRoot);
    %>
    </jsp:useBean>

    或者,如果你在DOMBean中定義一個setFile(String)方法:
    <jsp:useBean id="picture" scope="request" class="picturebeans.DOMPicture">
    <jsp:setProperty name="picture" property="file" value="<%=picturefile%>"/>
    </jsp:useBean>
    使用XMLEntryList

    為了克服DOM APIs的一些不足,我創建了一個類,叫做XMLEntryList。這個類執行了 Java Collections接口java.util.List,以及java.util.Map的get和put方法,它提供了一套更直觀的方法來在一個簡單的XML樹結構中往返移動。你可以使用Collections API的標準抽象(abstraction)來進行象獲得迭代或子視圖等。在EntryList的每一個入口都有一個鍵 key和一個值,就象Map一樣;鍵就是子結點(child nodes)的名字,而值要么是字符串,要么是下一級(child)XMLEntryLists。
    XMLEntryList并不意味著可以完全代替DOM。它還無法執行某些DOM的功能。但是,它是一個方便的外殼(wrapper)在你的XML數據結構上用于執行基本的getting, setting和 list-oriented 功能。例如,你可以使用這樣的寫法來得到圖片node的caption元素:
    String caption = (String)picturelist.get("caption");
    caption字段的值早已被作為一個字符串分析和存儲了。
    緩存 Caching

    盡管有很多優點,分析一個XML文件總是需要耗費時間。為了改進基于XML的應用的性能,你需要使用某種緩存技術。這種緩存必須在內存中保存XML對象,記住它們來自哪一個文件。如果對象被加載以后文件被修改了,那么對象需要重新加載。我開發過一個用于這種數據結構的簡單方法,叫做CachedFS.java。你可以供給一個CachedFS 調用返回功能(function),使用實際執行xml分析的內部類,將文件轉為一個對象。cache于是可以在內存中存儲那個對象。
    這里是創建cache的代碼,這一對象有application scope,所以此后的請求可以使用同一對象cache。我將把這些代碼放到init.jsp,這樣你就不必將這些初始化的代碼剪貼到其他JSP文件中去了。總之,你必須在一個公共的地方定義application-scope對象。
    <jsp:useBean id="cache" class="com.purpletech.io.CachedFS" scope="application">
    <% cache.setRoot(application.getRealPath("/"));
    cache.setLoader( new CachedFS.Loader() {
    // load in a single Picture file
    public Object process(String path, InputStream in) throws IOException
    {
    try {
    Document doc = DOMUtils.xml4jParse
    (new BufferedReader(new InputStreamReader(in)));
    Element nodeRoot = doc.getDocumentElement();
    nodeRoot.normalize();
    Picture picture = new DOMPicture(nodeRoot);
    return picture;
    }
    catch (XMLException e) {
    e.printStackTrace();
    throw new IOException(e.getMessage());
    }
    }
    });
    %>
    </jsp:useBean>

    XPath

    XPath在XML tree中是一個簡單的用于定位node的語法。它比 DOM更容易使用,因為當你要轉入另一個node時不必每次都要產生方法調用,你可以把整個路徑嵌入到一個字符串中去,例如:
    /picture/thumbnails/image[2].
    Resin產品包含了一個XPath處理器,你可以將它加入到自己的應用中去。你可以使用 Caucho XPath對象加載于其自身,不必購買Resin體系的其它產品。
    Node verse = XPath.find("chapter/verse", node);
    Resin也包含有一個腳本語言,與JavaScript兼容,允許在jsp中對XPath和XSL的簡單存取。
    XSL

    這篇文章討論了在JSP中嵌入Java來從XML node中展開數據。完成做同樣工作還可以有另外一種常見的模型:Extensible Stylesheet Language (XSL)。這一模型和JSP模型有著根本的不同。在JSP中,主要內容是HTML,它包含了一些Java代碼片段;而在XSL中,主要內容是XSL文檔,它包含了一些HTML片段。如果要討論XSL和 Java/JSP之間的關系,這里的空間已經不夠了。在JavaWorld雜志中將有一篇文章來探討如何同時使用XSL和JSP。
    目前的結論和未來的發展之路

    在讀完這篇文章后,相信你應該有了一個JSP-XML應用及其強大威力的很好的思路及結構認識。然而你也要知道一些它的局限。
    開發JSP-XML應用中最令人煩悶的是為每一個 XML schema中的元素element創建JavaBean。XML Data Binding 組織正在開發一種技術,可以為每一個給定的schema自動生成Java類。同樣的,我也開發了一種原型-開放源碼的Java-XML data binding技術。另外,IBM alphaWorks最近也推出了XML Master, 或稱為XMas,這是另一種XML-Java data binding系統。
    另外一種可能性是擴展文件系統的功能,建立一些更加強大的功能,如查詢和事務處理。自然地,我也開始期望這種功能類型也可以作為開放源碼工程來得到發展。那么,有沒有誰愿意寫一個XML搜索引擎?
    posted on 2007-01-16 22:52 EricWong 閱讀(177) 評論(0)  編輯  收藏 所屬分類: Java
    主站蜘蛛池模板: 一级毛片在线完整免费观看| 亚洲成aⅴ人片在线观| 亚洲av无码专区首页| www.999精品视频观看免费| 亚洲午夜在线电影| 日韩免费无码一区二区三区 | 美女黄频免费网站| 国产精品免费小视频| 亚洲AV无码一区二区大桥未久| 大学生美女毛片免费视频| 亚洲日韩精品无码AV海量| 永久免费av无码不卡在线观看| 久久久久se色偷偷亚洲精品av | 全免费一级午夜毛片| 亚洲av色香蕉一区二区三区| 免费一级国产生活片| 人成电影网在线观看免费| 亚洲精品无码久久一线| 99精品视频免费观看| 亚洲国产成a人v在线观看| 免费高清资源黄网站在线观看| 久久精品国产亚洲av品善| 亚洲成a人一区二区三区| 国产成人无码免费网站| 亚洲AV无码乱码国产麻豆| 麻豆成人久久精品二区三区免费| 亚洲精品综合久久中文字幕| 人禽杂交18禁网站免费| 亚洲另类无码专区丝袜| 2022中文字字幕久亚洲| 日本免费久久久久久久网站| 亚洲国产福利精品一区二区| 最近中文字幕mv免费高清视频7| 美女视频黄视大全视频免费的| 亚洲国产精品无码成人片久久| 2021在线永久免费视频| 老司机亚洲精品影院在线观看| 亚洲精品午夜无码电影网| 很黄很色很刺激的视频免费| 污污视频免费观看网站| 亚洲国产一区在线|