JiBX初步
http://numenzq.iteye.com/blog/153919
作者:曾巧(numenzq)
等級(jí):初級(jí)
摘要
JiBX是一款非常優(yōu)秀的XML(Extensible Markup Language)數(shù)據(jù)綁定框架。它提供靈活的綁定映射文件實(shí)現(xiàn)數(shù)據(jù)對(duì)象與XML文件之間的轉(zhuǎn)換;并不需要你修改既有的Java類(lèi)。另外,另外,它的轉(zhuǎn)換效率是目前很多開(kāi)源項(xiàng)目都無(wú)法比擬的。
?
正文
XML已經(jīng)成為目前程序開(kāi)發(fā)配置的重要組成部分了,而可以用來(lái)操作XML文件的開(kāi)源項(xiàng)目也逐漸成長(zhǎng)起來(lái),比如說(shuō)流行的:Digester、XStream、Castor、JDOM、dom4j、xalan等等,當(dāng)然也少不了專(zhuān)門(mén)為Java語(yǔ)言設(shè)計(jì)的xml數(shù)據(jù)綁定框架JiBX。它的主要有轉(zhuǎn)換效率高、配置綁定文件簡(jiǎn)單、不需要操作xpath文件、不需要寫(xiě)屬性的get/set方法、對(duì)象屬性名與xml文件element名不要相同等優(yōu)點(diǎn)。由于JiBX項(xiàng)目有比較完整的文檔和例子;所以在下面的文章中,我主要會(huì)介紹使用JiBX需要注意的細(xì)節(jié)問(wèn)題。
???
內(nèi)容
l???????? JiBX工作機(jī)制
l???????? 為何JiBX如此高效
l???????? JiBX綁定文件
l???????? 在ant中運(yùn)行綁定
l???????? 基本類(lèi)型與默認(rèn)值
l???????? 使用char時(shí)要小心
l???????? 使用接口時(shí)需給出工廠(chǎng)方法
l???????? 如何使用Map
l???????? 中文問(wèn)題又來(lái)了
l???????? 概要
?
JiBX工作機(jī)制
使用JiBX綁定xml文檔與java對(duì)象需要分兩步走,第一步是綁定xml文件,也就是映射xml文件與java對(duì)象之間的對(duì)應(yīng)關(guān)系;第二步是在運(yùn)行時(shí),實(shí)現(xiàn)xml文件與java實(shí)例之間的互相轉(zhuǎn)換;這時(shí),它已經(jīng)與綁定文件無(wú)關(guān)了,可以說(shuō)是完全脫耦了。
在運(yùn)行程序之前,需要先配置綁定文件并進(jìn)行綁定,在綁定過(guò)程中它將會(huì)動(dòng)態(tài)的修改你程序中相應(yīng)的class文件,主要是生成對(duì)應(yīng)對(duì)象實(shí)例的方法和添加被綁定標(biāo)記的屬性JiBX_bindingList等。它使用的技術(shù)是BCEL(Byte Code Engineering Library),BCEL是Apache Software Foundation 的Jakarta 項(xiàng)目的一部分。也是目前 Java classworking 最廣泛使用的一種框架,它可以讓您深入 JVM 匯編語(yǔ)言進(jìn)行類(lèi)操作的細(xì)節(jié)。在JiBX運(yùn)行時(shí)轉(zhuǎn)換時(shí),它使用了目前比較流行的一個(gè)技術(shù)XPP(Xml Pull Parsing),這也正是我下面一個(gè)item要將到的為何JiBX如此高效。
?
為何JiBX如此高效
在說(shuō)明這個(gè)之前,先給大家介紹數(shù)據(jù)綁定轉(zhuǎn)換中兩個(gè)通用概念:Unmarshal(數(shù)據(jù)分解)和Marshal(數(shù)據(jù)編排);從字面意思也很容易理解,Unmarshal是將xml文件轉(zhuǎn)換成java對(duì)象,而Marshal則是將java對(duì)象編排成規(guī)范的xml文件。JiBX在Unmarshal/Marshal上如此高效,這要?dú)w功于使用了XPP技術(shù),而不是使用基于樹(shù)型(tree-based)方式,將整個(gè)文檔寫(xiě)入內(nèi)存,然后進(jìn)行操作的DOM(Document?Object Model);也不是使用基于事件流(event stream)的SAX(Simple API?for Xml)。XPP使用的是不斷增加的數(shù)據(jù)流處理方式,同時(shí)允許在解析xml文件時(shí)中斷。JiBX在Unmarshal/Marshal的性能測(cè)試數(shù)據(jù)可以參考下面這篇文章《Java 中的 XML: 數(shù)據(jù)綁定,第 2 部分:性能》。
???
在ant中運(yùn)行綁定
JiBX提供了一個(gè)ant tasks來(lái)支持綁定操作;當(dāng)然,你也可以直接在cmd line下執(zhí)行綁定操作,綁定時(shí)用的包是jibx-bind.jar和bcel.jar;
在命令行下執(zhí)行綁定操作:java -jar jibx-bind.jar binding.xml。
如果要在ant下使用則可參考如下代碼:
<target name="bind" depends="compile">
<echo message="Running JiBX binding compiler" />
??? <taskdef name="bind" classname="org.jibx.binding.ant.CompileTask">
??????? <classpath>
??????????? <pathelement location="${basedir}/lib/jibx/jibx-bind.jar" />
??????? </classpath>
??? </taskdef>
??? <bind verbose="true" load="true">
??????? <bindingfileset dir="${bind.dir}">
??????????? <include name="binding(001).xml" />
??????????? <include name="binding(002).xml" />
??????????? ……
??????? </bindingfileset>
??????? <classpath refid="common-classpath" />
??? </bind>
</target>
???
基本類(lèi)型與默認(rèn)值
在JiBX綁定java對(duì)象時(shí),如果你使用了基本類(lèi)型,又使用了字段為可選值時(shí),你得檢查實(shí)際值與你的期望值是否相等。這樣說(shuō)起有點(diǎn)模糊,舉個(gè)例子說(shuō)明吧。如果java類(lèi)里有一個(gè)名為intValue 的int類(lèi)型的字段和一個(gè)名為stringValue的String類(lèi)型的字段,同時(shí)又在綁定文件中為這兩個(gè)字段配置為usage="optional",如:
<value name="intValue" field="intValue" usage="optional"/>
<value name="stringValue" field="stringValue" usage="optional" />
也就是說(shuō)這兩個(gè)字段為可選值,可有可無(wú)。我們?cè)诰幣舩ml文件時(shí),我們可以通過(guò)判斷stringValue是否等于null來(lái)確認(rèn)是否要在xml文件里顯示該element;而該字段是基本類(lèi)型,比如說(shuō)之前說(shuō)的intValue,就不能通過(guò)null來(lái)判斷了,JiBX的做法是判斷基本類(lèi)型是否等于默認(rèn)值,也就是說(shuō)判斷intValue是否等于0;如果是0,就不顯示該element,為非0值時(shí),才能顯示該element。
這樣講解后,你應(yīng)該得出一個(gè)結(jié)論,如果讓基本類(lèi)型為可選項(xiàng)時(shí),是無(wú)法輸出默認(rèn)值的。在解決這個(gè)問(wèn)題上,我們不使用基本類(lèi)型就行了,JDK5.0也支持自動(dòng)裝箱和拆箱了,再某些屬性聲明時(shí)不是用基本類(lèi)型對(duì)我們的影響并不是很大;或者寄希望于JiBX以后的版本實(shí)現(xiàn)裝箱和拆箱操作。
?
使用char時(shí)要小心
上面提到了在要綁定的字段里不推薦使用基本類(lèi)型,如果你一定要使用基本類(lèi)型,就得小心使用char類(lèi)型,因?yàn)閏har類(lèi)型比較特殊,你可以把它看作是只有一個(gè)字符的String,也可以看成是0-65535之間的一個(gè)數(shù)字,所以在JiBX使用時(shí),你需要明確該類(lèi)型字段在轉(zhuǎn)換時(shí)的序列化和反序列化操作。幸運(yùn)的是,JiBX提供了這樣的序列化和反序列化類(lèi),在綁定文件里應(yīng)加上如下可選屬性:
<value name="stringValue" field="stringValue"
serializer="org.jibx.runtime.Utility.serializeCharString" deserializer="org.jibx.runtime.Utility.deserializeCharString"/>
???
使用接口時(shí)需給出工廠(chǎng)方法
從xml文件轉(zhuǎn)換到j(luò)ava對(duì)象時(shí),是先要?jiǎng)?chuàng)建該類(lèi)的實(shí)例的,如果轉(zhuǎn)換的是一個(gè)實(shí)體類(lèi),創(chuàng)建實(shí)例就不會(huì)有什么問(wèn)題,但是如果我們要使用接口編程,轉(zhuǎn)換的對(duì)象就是一個(gè)接口,則會(huì)出現(xiàn)錯(cuò)誤,因?yàn)镴iBX并不清楚你需要?jiǎng)?chuàng)建這個(gè)接口的那個(gè)實(shí)例,這將會(huì)導(dǎo)致錯(cuò)誤;所以我們需要在綁定文件中指明該接口的創(chuàng)建工廠(chǎng)方法。例如:我們聲明一個(gè)List的屬性listValue,想要它指向一個(gè)ArrayList的實(shí)例,我們則需要寫(xiě)一個(gè)返回ArrayList實(shí)例的工廠(chǎng)方法getArrayListInstance;并在綁定文件中添加factory可選屬性,如下:
<collection field="listValue"
factory="com.gelc.JiBXInterfaceFactory.getArrayListInstance" />
??? 另外值得一提的就是,JiBX例子里的工廠(chǎng)方法的modifier是private,我用JUint對(duì)代碼進(jìn)行測(cè)試不會(huì)有問(wèn)題,但是用ant運(yùn)行同樣的測(cè)試,就會(huì)有IllegalAccessError,這是JiBX存在的一個(gè)Bug;對(duì)于該問(wèn)題,我建議將modifier改為public,這樣就不會(huì)出現(xiàn)問(wèn)題。
???
如何使用Map
??? 在JiBX的核心包里是不支持Map類(lèi)型的轉(zhuǎn)換的,不過(guò)你不用擔(dān)心,在JiBX的jibx-extras.jar附加包里提供了對(duì)Map的支持。你想使用Map還需要為它重寫(xiě)marshal/ummarshal方法,你不要被這個(gè)給嚇倒了,因?yàn)镴iBX已經(jīng)為你提供了這個(gè)實(shí)現(xiàn)框架,你只需要作相應(yīng)的修改就ok了。如果你想了解更多,可以參考JiBX提供的定制JiBX綁定方法指南。
???
中文問(wèn)題又來(lái)了
??? 說(shuō)到j(luò)ava項(xiàng)目中的中文問(wèn)題,我相信很多開(kāi)發(fā)者都遇到過(guò),JiBX對(duì)中文的支持也不太讓人滿(mǎn)意,因?yàn)镴iBX只支持Java標(biāo)準(zhǔn)的字符集,也就是說(shuō)我們常用的GB2312和GBK不在支持行列之內(nèi),如果你用的是UTF-8來(lái)處理中文,則沒(méi)有任何問(wèn)題,但是你想用GB2312或GBK編碼來(lái)實(shí)現(xiàn)轉(zhuǎn)換的話(huà),則需要你自己實(shí)現(xiàn)GB2312和GBK的Escaper類(lèi),重寫(xiě)writeAttribute(String, Writer)、writeCData(String, Writer)和writeContent(String, Writer)方法,由于GB2312和GBK的編碼規(guī)則是相同的,只是字符集大小不一樣,所以你可以讓同一個(gè)Escaper來(lái)處理這兩種編碼。
???
概要
JiBX 是一款高性能的數(shù)據(jù)綁定框架。如果xml文件格式比較固定,同時(shí)數(shù)據(jù)轉(zhuǎn)換比較頻繁時(shí),可以考慮讓它來(lái)助你一臂之力。
???
更多信息
·JiBX Project index
http://jibx.sourceforge.net/
·Extensible Markup Language
http://www.w3.org/XML/
·BCEL
http://jakarta.apache.org/bcel/
·Xml Pull Parsing
??? http://www.xmlpull.org/?
?
總結(jié)
- 上一篇: 从一个实例看jaxb的强大
- 下一篇: JSF入门