摘要本文從Java EE系統中對XML應用的需求出發詳細論述了XML在Java企業級應用系統中的若干問題內容涵蓋XML的解析處理XML的與Java的相互轉換XML的展示與抓取XML數據的查詢與持久化這幾個方面並重點論述了企業應用中XML與Java的轉換的技術難題並給出了一個實際可行的解決方案
一XML在Java中應用的概述
XML是一種可擴展標記語言(EXtensible Markup Language)於年月日被確立為 WC 標准由於是一種標記語言這使得成為XML跨平台的用於傳輸信息且獨立於軟件和硬件的工具
XML設計的目的是為了描述數據它使用使用文件類型聲明(DTD)或者 XML Schema 來描述數據規范帶有 DTD 或者 XML Schema 的 XML 被設計為具有自我描述性XML標簽沒有被預定義您必須自行定義標簽
XML與HTML的最大的區別是兩者目的不同XML作為數據載體來描述數據而HTML是為了格式化和展示數據
在Java EE應用中XML主要用來描述配置和數據的交換配置信息描述是最常見不過的了比如Java Web應用的描述符webxml包括很多開源框架的配置信息數據交換主要是XML的數據與其他格式的數據的轉換XML與JavaXML與數據庫表記錄XML與HTML等轉換
二XML在Java應用存在的若干問題
Java是一門面向對象的語言在應用XML時不可避免存在以下幾個方面的問題
XML數據解析
XML數據的存儲
XML數據的轉換
XML數據的查詢
XML數據的形成
XML數據的展示
這些方面我們可以用一個模式圖來表示如下圖
上圖是Java企業應中XML數據流圖這個圖分左右兩不部分左邊是XML數據的展示和抓取部分主要應用與客戶端右邊是Java對象的持久化技術在服務端不難看出在客戶端和服務器端之間還應該有中間一個轉換器工廠將XML與Java對象聯系起來這個應用才完整中間這個雙向的轉換器是企業應用中的難點本文重點要論述的內容
三XML的數據的客戶端展示與抓取
XML數據展示是Java EE 應用中客戶端的首要職責XML數據的展示技術很多常見的有XSLTXML數據島技術AJAX或者其他客戶端腳本技術都可以完成數據的展示這些技術都是目前比較流行的技術具體選擇應該根據技術復雜度靈活性軟件需求等方面來考慮 有關數據島的原理如下
在HTML中通過使用非官方的 <xml> 標簽可用來創建 XML 數據島這項技術首先在Internet Explorer中得以支持其他浏覽器的支持程度還需要進一步考證
數據島注入是在jsp或者HTML頁面中嵌入一個<xml id=[IslandId]src=[Islandxml]></xml>的標簽來實現其中id是表示數據島標識src是數據島資源名稱
在客戶端請求帶有數據島的頁面時首先通過JavaScript組件將數據島中的數據展示到頁面的表單域當客戶端填寫完成數據之後通過JavaScript組件將填寫後的數據改寫注入到XML數據島中然後將數據島數據發送給服務器端響應請求
另外除了數據島技術之外還可以通過XSLT來展示XML數據這個展示也很方便但缺點是難以編寫XSLT的文檔也難以實現復雜交互因此實際中主要用於XML數據的格式化輸出
XML是數據的載體通過相應的模板或組件技術可以方便將XML轉換PDFExcelHTML文檔等等這些一般都依賴一些組件工具來完成
XML數據的抓取是客戶端另一個重要職責一般來說用戶通過浏覽器將數據發送給服務器在請求發出之前應該通過一種策略將請求數據抓取為XML然後將所有請求的數據一次性發送給服務器服務器拿到這個XML數據做一個XML到Java的轉換然後處理請求業務
XML是客戶端抓取是XML數據的來源之一另外還可以將關系數據庫表記錄封裝為XML數據
從客戶端抓XML常常通過JavaScript結合數據島技術來實現這需要為頁面數據信息模型建立XML數據的模板然後以數據島的方法注入頁面頁面在數據的展示修改保存都直接操作數據島中的XML結果將以XML格式的文本發送給服務器這裡面有兩個問題需要注意其一如何定義合理的XML數據模型或者模板其二基於數據安全性考慮XML模板應該遵循最小原則盡可能暴露XML數據島中最少的數據信息
四XML文檔的解析
當客戶端攜帶XML數據將請求發送給服務器端的處理程序一般都需要進行XML數據的提取和轉化比如將XML通過Java XML API或者DomjJdom等解析解析出來的數據既可以構建Java Bean對象也可以直接將解析出來的數據參與計算或控制這些都是根據實際需要來確定
XML數據Java解析是Java應用XML的基礎也是後面要講述的XML-Java數據轉換器實現的基礎
目前Java XML解析器有很多並且基本上都是開源的組件解析原理有二使用基於事件的XML簡單API(Simple API for XML)稱為SAX和基於樹和節點的文檔對象模型(Document Object Module)稱為DOM
Sun公司提供了Java API for XML Parsing(JAXP)接口來使用SAX和DOM通過JAXP可以使用任何與JAXP兼容的XML解析器來處理XML但事實上並不是所有的Java XML解析工具都實現了JAXP所提供的接口Domj就是其中的一個但非常優秀已成為Java XML解析的事實標准
在使用Java組件或者API解析XML之前應該對XML DOM的概念有個全面認識這是解析XML基礎有關使用某個解析器解析XML的技術都是解析器API的如何應用問題在此不做具體介紹因為相關的書籍文章比比皆是
五XML與Java對象的相互轉換
為什麼要在XML與Java之間做轉換呢?
首先先分析一下典型的客戶端要完成一次注冊會員請求過程客戶填寫登記信息JavaScript組件抓取數據寫入數據島然後將攜帶XML數據島信息將請求服務器端處理服務器端接收到請求後獲取XML數據並封裝為不同的實體對象然後通過ORMapping組件(比如Hibernate)寫入到數據庫當用戶需要修改注冊信息時需要從數據庫取出數據通過ORMapping組件轉換為Java實體對象然後將Java實體對象轉換為XML在注入JSP或者HTML頁面的數據島並展示到注冊信息修改的頁面上將這兩個過程用一個圖形標識如下
從上圖可以看出客戶端請求會發送到服務層去做處理而服務層暴露給外部只有接口方法這些方法的參數大多都是和領域活動層密切相關的對象和參數服務層也不接受XML數據作為參數這時候在請求到達服務層之間將請求的XML數據轉換為Java Object是非常有必要的相反當修改登記信息時客戶端會請求要修改登記信息通過服務層查找到要修改的信息後轉換為XML注入到XML數據島完成後再做保存操作即可
從上面的過程看來存在一個迫切要解決的問題就是XMLJava Object之間的相互轉換這個轉換相當於一個橋梁將XML格式數據與頁面表單域Java對象數據庫表記錄有機的聯系起來從而實現自由的交換處理
至於XML數據的展示與抓取Java對象通過ORMapping框架實現持久化以及持久化數據轉換為Java對象這些技術已經相當的成熟有很多的開源框架可以實現大名鼎鼎的Hibernate就是一個優秀的ORMapping框架並且得到的廣泛的應用因為本文將在下面的篇幅中不去深刻介紹這些技術而將花費大篇幅去分析講述XML與Java之間的相互轉換和處理
通常對於一個Java EE應用系統來說領域層的實體數量都是相當多的從幾十個到上千都有可能如果單純用XML解析技術針對每個實體完成轉換將是相當麻煩和復雜的工作不但會導致很多重復的工作而且實體增加屬性或刪除屬性的時候解析轉換也需要隨之改變維護起來無異於是異常噩夢給軟件項目帶來巨大的風險
因此可以考慮設計一個轉換器工廠任何的實體對象都可以通過轉換器工廠自動轉換為XML並且任何的XML通過轉換器工廠也自動生成Java對象從而將轉換的過程簡化這個轉換是由程序自動維護的這樣前台頁面程序員僅僅關注自己頁面的書寫與展示後台的設計人員只考慮領域模型的設計以及服務層的開發節省了前後台人員相互交流的時間也大大的增加的軟件的健壯性和維護的代價減少了項目的風險
如何設計一個轉換器工廠呢?下面將以登記業務為利詳細說明如何構建這樣一個轉換器工廠
為了實現這個轉換器工廠首先要考慮的是如何實現一個轉換器將一個對象轉換為XML並且如何讓這個過程可以逆轉?因為這是實現一個轉換工廠最基礎的工作
在此不得不引入一個開源的組件XstreamXStream是一個Java和XML相互轉換的工具使用非常的簡單並且可以自定義轉換的過程但是這個組件僅能做的就是這些最基本的工作有了這個組件我們可以不用考慮具體一個Java對象和XML之間問題了而是將注意力轉移到一個轉換器工廠的構建上去
在構建Java Object與XML轉換器工廠之前應該對這個工廠的的功能加以描述
工廠的目標是生產轉換器轉換器的生成應該是自動的傳入一個Java類就應該生成一個轉換器對象
轉換器的應該是雙向的可以從Java對象生成XML也可以反向從XML轉向Java
轉換器的生成應該是可配置的而不是手動編碼去構建並且轉換類支持類的組合
下面就以一個用戶登錄的例子來說明如何實現這個轉換器工廠的構建在此之前我們先看看實體模型以及目標的XML數據模板
上面是模型的UML類圖一個User類中包含兩個相關聯的類UserProfile和Address類一個用戶對應一個UserProfile(用戶的其他信息)和一組Address(用戶地址信息)我們就以這樣一個模型為研究對象實現一個轉換器工廠
在實現轉換器之前先看看XStream是如何做到讓對象轉換為XML的
XStream的應用的核心就是要構建出實體模型然後將實體按照所表達的信息組合成許多單元然後每個單元確定作為完整信息模型在本例中UserAddressUserProfile三個實體類就是一個單元User就是一個完整的信息模型表述用戶的信息現在假設我們已經擁有了一個User對象如何將這個對象轉換為XML代碼如下
//創建轉換器對象
XStream xStream = new XStream();
//為類所生成的節點添加別名
xStreamalias(User Userclass);
xStreamalias(Address Addressclass);
xStreamalias(UserProfile UserProfileclass);
//為用戶信息模型的成員加上別名
xStreamaliasField(UserProfile Userclass userProfile);
//將User對象轉換為XML數據
String xml = xStreamtoXML(user);
Systemoutprintln(xml);
我們可以看到這段代碼非常簡單甚至我們可以直接new一個轉換器出來直接將對象轉換為XML但是一般來說別名是非常必要的這段代碼打印的結果如下
<User>
<id></id>
<username>admin</username>
<password></password>
<UserProfile>
<id></id>
<sex>M</sex>
<birthday> :: CST</birthday>
<telphone></telphone>
<email></email>
<userId></userId>
</UserProfile>
<addresses class=set>
<Address>
<id></id>
<addr>鄭州市花園路</addr>
<postCode></postCode>
</Address>
<Address>
<id></id>
<addr>鄭州市經三路</addr>
<postCode></postCode>
</Address>
</addresses>
</User>
如果我們需要將這個XML再轉換為Java Object那麼一樣的容易只要將這個XML傳遞給相對應的轉換器即可代碼如下
User u =(User)xStreamfromXML(xml);
以上代碼還不足以給您帶來驚喜因為企業應用中的信息模型動辄好幾百個如果一個一個去寫這些轉換器是件相當耗時而且容易出錯的工作必須想辦法構建一個轉換器工廠讓工廠自動構建出所需要的轉換器
為此可以考慮定義一個配置文件將每個信息模型做為一個單元寫入其中並且在這些單元內部詳細定義各個域的別名等信息這樣通過配置文件就可以獲取到轉換構建信息從而為工廠產品的生產提供了依據構建的配置文件信息如下
<?xml version= encoding=GBK?>
<!
Document : InfoUnitsxmlxml
Created on : 年月日 下午:
Author : leizhimin
Description:
Purpose of the document follows
>
<InfoUnits>
<User class =Userclass>
<ID en=id />
<MC en=username />
<MM en=password/>
<UserProfile class=UserProfileclass>
<ID en = id/>
<XB en = sex/>
<SR en =birthday/>
<DH en = telphone/>
<YJDZ en =email/>
<YHID en =userId/>
</UserProfile>
<AddressList>
<Address class = Addressclass>
<ID en = id/>
<DZ en = addr/>
<YB en = postCode/>
</Address>
</AddressList>
</User>
</InfoUnits>
未完待續```
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26542.html