jaxb 的使用介紹[轉載]

什麼是jaxb?
http://java.sun.com/xml/jaxb/about.html

主要能幹什麼?
當人們需要用java應用程序來訪問數據庫的時候,jdbc誕生了
當人們覺得頻繁的jdbc操作很繁瑣的時候,o/r mapping誕生了
當人們需要用java操作xml的時候,sax, dom誕生了
當人們覺得用dom操作xml很繁瑣的時候, jaxb誕生了
jaxb---將xml與java對象綁定的sun規範.

使用:
jaxb的bin目錄下有一個xcj.bat的批處理文件, 作用就是根據xml scheme文件比如xsd來生成java文件
sample.xsd
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
            jaxb:version="1.0" >
            <xsd:element name="registry" type="RegistryType"/>
           
            <xsd:complexType name="RegistryType">
                <xsd:sequence>
                    <xsd:element name="module" type="ModuleType"/>
                </xsd:sequence>
            </xsd:complexType>

            <xsd:complexType name="ModuleType">
                <xsd:sequence>
                    <xsd:element name="serviceFactory" type="ServiceFactoryType"/>
                    <xsd:element name="serviceClientFactory" type="ServiceClientFactoryType"/>
                </xsd:sequence>
                <xsd:attribute name="name" type="xsd:string"/>
            </xsd:complexType>

            <xsd:complexType name="ServiceFactoryType">
                <xsd:sequence>
                    <xsd:element name="service" type="ServiceType" minOccurs="0" maxOccurs="unbounded"/>
                </xsd:sequence>
                <xsd:attribute name="class" type="xsd:string">
                    <xsd:annotation>
                        <xsd:appinfo>
                            <jaxb:property name="clazz"/>
                        </xsd:appinfo>
                    </xsd:annotation>
                </xsd:attribute>
            </xsd:complexType>

            <xsd:complexType name="ServiceType">
                <xsd:attribute name="id" type="xsd:string"/>
                <xsd:attribute name="class" type="xsd:string">
                    <xsd:annotation>
                        <xsd:appinfo>
                            <jaxb:property name="clazz"/>
                        </xsd:appinfo>
                    </xsd:annotation>
                </xsd:attribute>
            </xsd:complexType>

            <xsd:complexType name="ServiceClientFactoryType">
                <xsd:sequence>
                    <xsd:element name="serviceClient" type="ServiceClientType"/>
                </xsd:sequence>
                <xsd:attribute name="class" type="xsd:string">
                    <xsd:annotation>
                        <xsd:appinfo>
                            <jaxb:property name="clazz"/>
                        </xsd:appinfo>
                    </xsd:annotation>
                </xsd:attribute>
            </xsd:complexType>

            <xsd:complexType name="ServiceClientType">
                <xsd:sequence>
                    <xsd:element name="serviceRender" type="ServiceRenderType" minOccurs="0" maxOccurs="unbounded"/>
                </xsd:sequence>
                <xsd:attribute name="id" type="xsd:string"/>
                <xsd:attribute name="class" type="xsd:string">
                    <xsd:annotation>
                        <xsd:appinfo>
                            <jaxb:property name="clazz"/>
                        </xsd:appinfo>
                    </xsd:annotation>
                </xsd:attribute>
                <xsd:attribute name="renderFactory" type="xsd:string"/>
            </xsd:complexType>

            <xsd:complexType name="ServiceRenderType">
                <xsd:attribute name="class" type="xsd:string">
                    <xsd:annotation>
                        <xsd:appinfo>
                            <jaxb:property name="clazz"/>
                        </xsd:appinfo>
                    </xsd:annotation>
                </xsd:attribute>
                <xsd:attribute name="id" type="xsd:string"/>
            </xsd:complexType>
</xsd:schema>
在cmd窗口下   xjc -p com.hairroot.jaxb sample.xsd
這個命令會在com/hairroot/jaxb的目錄下生成幾個interface, 並在com/hairroot/jaxb/impl下面生成各自的實現類,實現類看起來還是很複雜的。爲什麼這麼複雜,原因就是需要考慮很多的事情,比如進行marshal的時候,如果儘可能的將輸出跟輸入xml看起來一致的xml, 而不是元素,屬性的順序弄得亂七八糟的。

注意:除了生成的java文件之外,還有一個jaxb.properties, 和ser。這兩個東西是不能 丟的,否則會報錯。

unmarshall的操作:
兩種方式
    1)JAXBContext context = JAXBContext.newInstance("com.hairroot.jaxb");
          context.createUnmarshaller().unmarshal(new File("d:/hairroot/jaxb/sample.xml"));
    2)ObjectFactory factory = new ObjectFactory();
          factory.createUnmarshaller().unmarshal(new File("d:/hairroot/jaxb/sample.xml"));
    unmarshall返回的結果是一個object, 也就是根類型的一個實現類,可以強制轉型了之後進行其它的操作。

marshall的操作:
同樣有兩種方式
    1)JAXBContext context = JAXBContext.newInstance("com.hairroot.jaxb");
          Object root = context.createUnmarshaller().unmarshal(new File("d:/hairroot/jaxb/sample.xml"));
          context.createMarshaller().marshal(root, System.out);
    2)ObjectFactory factory = new ObjectFactory();
          Object root = factory.createUnmarshaller().unmarshal(new File("d:/hairroot/jaxb/sample.xml"));
          factory.createMarshaller().marshal(root, System.out);

Validation的操作現在略;

如何將xsd:data類型進行格式化的輸出:
    如果在schema中定義一個xsd:date類型,那麼jaxb會將其轉化爲java.util.Calendar的類型,然而這樣有個問題,如果 sample.xml中數據爲2005-03-09, 那麼進行marshal的操作後生成的xml爲2005-03-09+08:00, 解決方法, 在scheme中
                        <xsd:element name="shipDate" minOccurs="0">
                            <xsd:simpleType>
                                <xsd:annotation>
                                    <xsd:appinfo>
                                        <jaxb:javaType name="java.sql.Date" printMethod="toString" parseMethod="valueOf"/>
                                    </xsd:appinfo>
                                </xsd:annotation>
                                <xsd:restriction base="xsd:date"/>
                            </xsd:simpleType>
                        </xsd:element>

並且還需要在xsd的namespace中加入
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
            xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
            jaxb:version="1.0" >
這樣再進行xjc的時候不會報錯,而且輸入的date也就符合習慣了,如果不用
<jaxb:javaType name="java.sql.Date" printMethod="toString" parseMethod="valueOf"/>
則需要自己來寫一個實現類,詳細參考jaxb reference

如何處理java的一些保留字:
如果一個attribute的名字叫做class, 那麼xjc產生的java中就有一個getClass的方法, 這與java.lang.Object 的getClass()相沖突,解決方法:
                <xsd:attribute name="class" type="xsd:string">
                    <xsd:annotation>
                        <xsd:appinfo>
                            <jaxb:property name="clazz"/>
                        </xsd:appinfo>
                    </xsd:annotation>
                </xsd:attribute>
可以用<jaxb:property name="clazz"/>來指定xjc生成的java的方法爲getClazz()

jaxb1.0的問題:
目前我發現的主要問題是, attribute的輸入的順序跟schema中定義的順序不一致,網上看到sun的工程師認爲這不是一個很重要的問題,而且還認爲attribute的順序沒有辦法控制,這種藉口簡直好笑,如果能夠做得更好爲什麼不去做?
推薦解決方法:
在xjc生成了java文件了之後,去看一下impl下面的每一個類的serializeAttributes()方法,調整這個方法的對應的 attribute的處理的上下順序,就可以控制輸出的xml的attribute出現的先後順序,如此簡單的事情,sun的工程師竟然說沒有辦法控制,當忽悠變成了一種時尚...

原文見 http://hairroot.blogchina.com/hairroot/899157.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章