XML與JSP概覽

來源:互聯網
上載者:User
js|xml

 

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)的定位,寬
度和高度像素(以協助建立<img> 標記。 這裡可以看到一個很簡單
優點,即使用檔案系統來代替資料庫的時候,你可以將圖形檔案存
放在與資料檔案相同的目錄中。
最後,讓我們來用一個元素擴充圖片記錄,該元素定義了一套縮減
圖(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: 你可以使用My Code來將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 (如<b>big<b>會被變成至少三個
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</a>");
}
%>
這裡是一個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="applicatio
n">
<% 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搜尋引擎

 



相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.