XML和J2EE的完美結合
當前,Java 2平臺企業版(J2EE)架構在廠商市場和開發者社區中倍受推崇。作為一種工具,可擴展標記語言(XML)簡化了數據交換、進程間消息交換這一類的事情,因而對開發者逐漸變得有吸引力,并開始流行起來。自然,在J2EE架構中訪問或集成XML解決方案的想法也很誘人。因為這將是強大系統架構同高度靈活的數據管理方案的結合。
XML的應用似乎是無窮無盡的,但它們大致上可以分為三大類:
●簡單數據的表示和交換(針對XML的簡單API(SAX)和文檔對象模型(DOM)語法解析,不同的文檔類型定義(DTDs)和概要(schemas))
●面向消息的計算(XML-RPC(遠程過程調用),SOAP協議,電子化業務XML(ebXML))
●用戶界面相關、表示相關的上下文(可擴展樣式表語言(XSL),可擴展樣式表語言轉換(XSLT))
這幾類應用在J2EE架構中恰好有天然的對應:數據表示和交換功能是EJB組件模型中持久化服務(persistence services)的一部分,基于消息的通訊由Java消息服務(JMS)API來處理,而界面表示正是Java服務器頁面(JSP)和Java Servlets的拿手好戲。
在本文中,我們將看到當今基于J2EE的應用里,XML是如何在上述幾個方面進行應用的,以及在相關標準的未來版本中這些應用將會如何發展。
基礎:數據的表示和交換
原型化的XML應用(假設有的話)的內容通常是:數據以XML格式存放,為了進行顯示、修改甚至寫入某個XML文檔而經常被讀入到某個對象模型中。作為例子,假定我們正處理多種類型的媒體(圖品、視頻、文本文檔等等),并且用下面這個簡單的XML DTD來描述這些媒體的元數據:
以下是一個基于上述媒體DTD的XML文檔,描述了與某個課程講座相關的內容:
從Web或者企業級應用的角度看,能以這種方式訪問數據真是一種福音,因為它體現了高度的可移動性,使我們與元數據的實際資源本身隔離。這些資源可能來自一個關系數據庫系統、某種活動媒體服務器或者Web服務器上的一個靜態XML文檔,等等。如果想把這些數據加載到Java應用中,我們可以從當前眾多的Java語言XML解析器中選用一個,通過它將XML數據裝入一個DOM文檔,最后遍歷文檔,將所有這些數據轉換到我們應用系統的對象模型中。
下面是個簡單的基于DOM的解析程序,可對上述的媒體DTD進行解析。解析器用的是Apache Xerces:
MediaParser類的構造函數初始化了一個Xerces DOM解析器。parse()方法告訴解析器到哪個URL去找XML源,然后得到結果文檔并返回。loadAssets()方法調用parse()方法從某個XML源加載文檔,然后為文檔中找到的每個“media-asset”節點創建一個MediaAsset對象。
以下是一個使用MediaAsset類的例子:
因為篇幅的關系省略了MediaAsset類的詳細代碼,但應用模式依然是清晰的。MediaAsset類遍歷文檔的節點,當它碰到不同的子節點時,它用子節點的內容填充自己的成員數據。如果它發現了一個嵌套的子資源節點,它只需要創建一個新的MediaAsset對象,然后將子資源節點的數據填充到新對象的成員數據中。
實現上述處理的方法數不勝數。我們還可以使用其他的解析器或解析器架構,如Java API for XML Parsing (JAXP)。除了使用DOM模型外,事件驅動的SAX模型也可用于解析XML。類似的程序也可用來產生XML數據——前提是允許產生新的數據對象(在本例中是MediaAsset),它可將其相應的XML實體插入到DOM中,然后將DOM輸出到一個流中(諸如一個文件,一個Socket,或者一個HTTP連接...)。還有其他更高層次的標準,可將XML映射到Java對象的過程進一步自動化(或簡化)。例如,使用XML概要(Schema)和XML綁定處理引擎,您可以半自動地將滿足某個XML 概要的XML數據轉變成Java數據對象。代表性的引擎是Castor,是由ExoLab小組管理的一個開放源代碼項目的產物。上述使用Xerces DOM的簡單例子僅僅是演示了這一處理過程的底層模型。
上述示例表明,在Java環境中解析或產生XML是非常方便的,這與J2EE沒有必然關聯。格式化為XML的數據可以從應用程序的任何層次流入或輸出,這使得與外部系統的集成性無可限量。但我們能否以一種更為直接的方式將XML數據源集成到J2EE架構中去呢?
XML的應用似乎是無窮無盡的,但它們大致上可以分為三大類:
●簡單數據的表示和交換(針對XML的簡單API(SAX)和文檔對象模型(DOM)語法解析,不同的文檔類型定義(DTDs)和概要(schemas))
●面向消息的計算(XML-RPC(遠程過程調用),SOAP協議,電子化業務XML(ebXML))
●用戶界面相關、表示相關的上下文(可擴展樣式表語言(XSL),可擴展樣式表語言轉換(XSLT))
這幾類應用在J2EE架構中恰好有天然的對應:數據表示和交換功能是EJB組件模型中持久化服務(persistence services)的一部分,基于消息的通訊由Java消息服務(JMS)API來處理,而界面表示正是Java服務器頁面(JSP)和Java Servlets的拿手好戲。
在本文中,我們將看到當今基于J2EE的應用里,XML是如何在上述幾個方面進行應用的,以及在相關標準的未來版本中這些應用將會如何發展。
基礎:數據的表示和交換
原型化的XML應用(假設有的話)的內容通常是:數據以XML格式存放,為了進行顯示、修改甚至寫入某個XML文檔而經常被讀入到某個對象模型中。作為例子,假定我們正處理多種類型的媒體(圖品、視頻、文本文檔等等),并且用下面這個簡單的XML DTD來描述這些媒體的元數據:
| <!-- DTD for a hypothetical media management system --> <!-- Media assets are the root of the object hierarchy. Assets are also hierarchical - they can contain other assets. --> <!ELEMENT media-asset (name, desc?, type*, media-asset*, urn)> <!-- Metadata about the asset --> <!ELEMENT name (#PCDATA)> <!ELEMENT desc (#PCDATA)> <!ELEMENT type (desc, mime-type?)> <!ELEMENT mime-type (#PCDATA)> <!ELEMENT urn (#PCDATA)> |
以下是一個基于上述媒體DTD的XML文檔,描述了與某個課程講座相關的內容:
| <?xml version="1.0" ?><!DOCTYPE media-asset PUBLIC "-//Jim Farley//DTD Media Assets//EN" "http://localhost/Articles/Sun/dtds/media.dtd"> <media-asset> <name>第14講</name> <desc>與第14講相關的所有內容</desc> <!-- 內容對象"lecture 14"的一套子組件 --> <media-asset> <name>講座的幻燈片</name> <type> <desc>MS PowerPoint</desc> <mime-type>application/vnd.ms-powerpoint</mime-type> </type> <urn>http://javatraining.org/jaf/E123/lecture- 14/slides.ppt</urn> </media-asset> <media-asset> <name>講座的視頻片斷</name> <type> <desc>RealPlayer streaming video</desc> <mime-type>video/vnd.rn-realvideo</mime-type> </type> <urn>http://javatraining.org/jaf/E123/lecture- 14/lecture.rv</urn> </media-asset> <!-- 講座開始 --> <urn>http://javatraining.org/jaf/E123/lecture-14/index.jsp</urn> </media-asset> |
從Web或者企業級應用的角度看,能以這種方式訪問數據真是一種福音,因為它體現了高度的可移動性,使我們與元數據的實際資源本身隔離。這些資源可能來自一個關系數據庫系統、某種活動媒體服務器或者Web服務器上的一個靜態XML文檔,等等。如果想把這些數據加載到Java應用中,我們可以從當前眾多的Java語言XML解析器中選用一個,通過它將XML數據裝入一個DOM文檔,最后遍歷文檔,將所有這些數據轉換到我們應用系統的對象模型中。
下面是個簡單的基于DOM的解析程序,可對上述的媒體DTD進行解析。解析器用的是Apache Xerces:
| package jaf.xml; import java.util.*; import java.io.IOException; import org.w3c.dom.*; import org.xml.sax.*; // XML文檔解析程序,使用上述媒體DTD. public class MediaParser implements ErrorHandler { /** 使用Apache Xerces解析器 */ org.apache.xerces.parsers.DOMParser mParser = new org.apache.xerces.parsers.DOMParser(); /** 構造函數 */ public MediaParser() { // 告訴解析器驗證并解析文檔 try { mParser.setFeature( "http://xml.org/sax/features/validation", true); } catch (SAXException e) { System.out.println("Error setting validation on parser:"); e.printStackTrace(); } // 設置解析器的錯誤處理句柄 mParser.setErrorHandler(this); } /** 解析指定的URL,返回找到的XML文檔 */ public Document parse(String url) throws SAXException, IOException { mParser.parse(url); Document mediaDoc = mParser.getDocument(); return mediaDoc; } /** 解析指定URL的XML文檔,將內容轉換成 MediaAsset 對象 */ public Collection loadAssets(String url) throws SAXException, IOException { Document doc = parse(url); Collection assets = new LinkedList(); NodeList assetNodes = doc.getElementsByTagName("media-asset"); for (int i = 0; i < assetNodes.getLength(); i++) { Node assetNode = assetNodes.item(i); MediaAsset asset = new MediaAsset(assetNode); assets.add(asset); } return assets; } /** * 錯誤處理代碼(為簡潔起見省略了) */ } |
MediaParser類的構造函數初始化了一個Xerces DOM解析器。parse()方法告訴解析器到哪個URL去找XML源,然后得到結果文檔并返回。loadAssets()方法調用parse()方法從某個XML源加載文檔,然后為文檔中找到的每個“media-asset”節點創建一個MediaAsset對象。
以下是一個使用MediaAsset類的例子:
| package jaf.xml; import java.util.*; public class MediaAsset { // 資源元數據 private String mName = ""; private String mDesc = ""; private Collection mChildren = new LinkedList(); private Vector mTypes = new Vector(); private String mUrn = ""; protected MediaAsset(org.w3c.dom.Node assetNode) { // 為簡潔起見省略后面代碼 . . . } } |
因為篇幅的關系省略了MediaAsset類的詳細代碼,但應用模式依然是清晰的。MediaAsset類遍歷文檔的節點,當它碰到不同的子節點時,它用子節點的內容填充自己的成員數據。如果它發現了一個嵌套的子資源節點,它只需要創建一個新的MediaAsset對象,然后將子資源節點的數據填充到新對象的成員數據中。
實現上述處理的方法數不勝數。我們還可以使用其他的解析器或解析器架構,如Java API for XML Parsing (JAXP)。除了使用DOM模型外,事件驅動的SAX模型也可用于解析XML。類似的程序也可用來產生XML數據——前提是允許產生新的數據對象(在本例中是MediaAsset),它可將其相應的XML實體插入到DOM中,然后將DOM輸出到一個流中(諸如一個文件,一個Socket,或者一個HTTP連接...)。還有其他更高層次的標準,可將XML映射到Java對象的過程進一步自動化(或簡化)。例如,使用XML概要(Schema)和XML綁定處理引擎,您可以半自動地將滿足某個XML 概要的XML數據轉變成Java數據對象。代表性的引擎是Castor,是由ExoLab小組管理的一個開放源代碼項目的產物。上述使用Xerces DOM的簡單例子僅僅是演示了這一處理過程的底層模型。
上述示例表明,在Java環境中解析或產生XML是非常方便的,這與J2EE沒有必然關聯。格式化為XML的數據可以從應用程序的任何層次流入或輸出,這使得與外部系統的集成性無可限量。但我們能否以一種更為直接的方式將XML數據源集成到J2EE架構中去呢?