小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

使用JAXB從一個(gè)對(duì)象模型中產(chǎn)生XML文檔

 9loong 2008-05-29
使用JAXB從一個(gè)對(duì)象模型中產(chǎn)生XML文檔   [ http://tech.it168.com/j/2007-04-01/200704011813902.shtml ]
 
作者:IT168 gmplayer  2007-04-01
 
    引入
    Java提供各種方式來(lái)處理XML,其中包括: 
    使用簡(jiǎn)單的文件I/O或者javax.xml.stream.XmlStreamWriter. 
    使用XML序列化java.beans.XMLEncoder,它能夠產(chǎn)生一個(gè)Java Bean的XML表示法,同樣,ObjectOutputStream也能夠用來(lái)創(chuàng)建序列化對(duì)象的二進(jìn)制表示法。 
    使用專(zhuān)門(mén)的類(lèi)庫(kù)像XStream,直接使用SAX(XML的簡(jiǎn)單API)或者通過(guò)JAXP API來(lái)使用DOM(文檔對(duì)象模型)。 

    盡管XML和Java技術(shù)已經(jīng)在數(shù)據(jù)交換上已經(jīng)有成熟的模型,但是將一個(gè)Java對(duì)象模型映射到XML和將XML映射為Java對(duì)象模型還是有點(diǎn)神秘的??梢钥紤]使用JAXB作為一種解決方案,JAXB (Java Architecture for XML Binding)可以使你將XML轉(zhuǎn)換為Java數(shù)據(jù)綁定和從XML schemas產(chǎn)生Java類(lèi),反之也是可以的。它非常方便且容易使用,它提供了像XML驗(yàn)證和使用注釋和適配器進(jìn)行定制。下圖闡述了JAXB的用法:



    JAXB API在javax.xml.bind包中被定義,它是一系列的接口和類(lèi),從schema產(chǎn)生的代碼可以使應(yīng)用程序進(jìn)行通訊。JAXB API最主要的就是javax.xml.bind.JAXBContext類(lèi),JAXBContext是一個(gè)抽象的類(lèi),它可以管理XML/Java 綁定,也可以被看作為一個(gè)工廠(chǎng),因?yàn)樗峁?nbsp;

    Unmarshaller類(lèi)可以將XML轉(zhuǎn)換為Java變得連續(xù)并且可以隨意的驗(yàn)證XML(使用setSchema方法) 
    Marshaller類(lèi)使一個(gè)對(duì)象圖形到XML的轉(zhuǎn)換變得連續(xù)并且可以隨意的驗(yàn)證。 

    首先,JAXB通過(guò)使用schema generator能夠在一個(gè)XML schema中定義一系列的類(lèi),它也提供相反的操作,允許你通過(guò)schema compiler從一個(gè)給定的XML schema產(chǎn)生Java類(lèi)的集合。 

    schema compile將XML schema看作為輸入并產(chǎn)生一個(gè)Java類(lèi)和接口的包,這個(gè)接口反應(yīng)了在源schema中定義的規(guī)則。這些類(lèi)是被注釋使用一個(gè)可定制的Java-XML映射提供運(yùn)行時(shí)框架。 

    JAXB也可以使用schema generator從一個(gè)XML schema中產(chǎn)生一個(gè)Java對(duì)象層或者提供一個(gè)對(duì)象Java層來(lái)描述相應(yīng)的XML schema。運(yùn)行時(shí)框架提供了相應(yīng)的unmarshalling, marshalling和驗(yàn)證功能。也就是說(shuō),你可以從一個(gè)XML文檔轉(zhuǎn)換為一個(gè)對(duì)象圖形(unmarshalling)或者將一個(gè)對(duì)象圖形轉(zhuǎn)換為XML格式(marshalling)。 

    這些功能就是為什么JAXB經(jīng)常和Web service相關(guān)聯(lián)的原因。Web service使用API來(lái)將對(duì)象轉(zhuǎn)換為消息,該消息可以通過(guò)SOAP來(lái)進(jìn)行發(fā)送。本文所使用的例子就是一個(gè)虛擬音樂(lè)公司的地址薄的應(yīng)用。
    產(chǎn)生XML
    音樂(lè)公司銷(xiāo)售它的音樂(lè)產(chǎn)品像樂(lè)器,唱片等,在它的地址薄中存儲(chǔ)著兩種類(lèi)型的客戶(hù):個(gè)體和公司。每一個(gè)客戶(hù)都有一個(gè)家庭地址和一系列的發(fā)貨地址。發(fā)貨地址可以是周末或早上有效,這些信息可以以標(biāo)簽的形式添加到地址薄中。其形式如下圖所示:


    該公司想要以XML形式發(fā)送一些客戶(hù)的信息給合作伙伴,因此它需要一個(gè)給定客戶(hù)的對(duì)象模型的XML文檔。使用JAXB實(shí)現(xiàn)起來(lái)很容易。下列代碼創(chuàng)建了一個(gè)個(gè)體的實(shí)例并設(shè)置了他的屬性(first name ,last name)一個(gè)家庭地址,兩個(gè)發(fā)貨地址。對(duì)象都設(shè)置好以后使用javax.xml.bind.Marshaller來(lái)產(chǎn)生個(gè)體對(duì)象的XML表示。 
    Listing 1: Creates an XML Representation of an Individual
// Instantiates Tag objects Tag tag1 = new Tag("working hours"); Tag tag2 = new Tag("week-ends"); Tag tag3 = new Tag("mind the dog"); // Instantiates an individual object with home address calendar.set(1940, 7, 7, 0, 0, 0); Individual individual = new Individual(1L, "Ringo", "Starr", "+187445",
"ringo@star.co.uk", calendar.getTime()); individual.setHomeAddress(new Address(2L, "Abbey Road", "London", "SW14", "UK")); // Instantiates a first delivery address Address deliveryAddress1 = new Address(3L, "Findsbury Avenue", "London", "CE451", "UK"); deliveryAddress1.addTag(tag1); deliveryAddress1.addTag(tag3); individual.addDeliveryAddress(deliveryAddress1); // Instantiates a second delivery address Address deliveryAddress2 = new Address(4L, "Camden Street", "Brighton", "NW487", "UK"); deliveryAddress2.addTag(tag1); deliveryAddress2.addTag(tag2); individual.addDeliveryAddress(deliveryAddress2); // Generates XML representation of an individual StringWriter writer = new StringWriter(); JAXBContext context = JAXBContext.newInstance(Customer.class); Marshaller m = context.createMarshaller(); m.marshal(individual, writer); System.out.println(writer);
    這段代碼使用靜態(tài)方法newInstance來(lái)產(chǎn)生JAXBContext的一個(gè)實(shí)例。創(chuàng)建Marshaller對(duì)象,然后調(diào)用marshal方法產(chǎn)生一個(gè)個(gè)體對(duì)象的XML表示,即StringWinter。 
    接下來(lái)要做的就是增加@XmlRootElement注釋到Customer類(lèi)中,@XmlRootElement注釋通知JAXB被注釋的類(lèi)是XML文檔的根元素。如果該注釋丟失,JAXB將拋出異常。如果增加了注釋并運(yùn)行程序?qū)?huì)得到下列XML文檔: 
    Listing 2: XML Representation of an Individual
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <customer> <deliveryAddresses> <city>London</city> <country>UK</country> <id>3</id> <street>Findsbury Avenue</street> <tags> <name>working hours</name> </tags> <tags> <name>mind the dog</name> </tags> <zipcode>CE451</zipcode> </deliveryAddresses> <deliveryAddresses> <city>Brighton</city> <country>UK</country> <id>4</id> <street>Camden Street</street> <tags> <name>working hours</name> </tags> <tags> <name>week-ends</name> </tags> <zipcode>NW487</zipcode> </deliveryAddresses> <email>ringo@star.co.uk</email> <homeAddress> <city>London</city> <country>UK</country> <id>2</id> <street>Abbey Road</street> <zipcode>SW14</zipcode> </homeAddress> <id>1</id> <telephone>+187445</telephone> </customer>

    通過(guò)一個(gè)注釋@XmlRootElemen,一個(gè)Marshaller對(duì)象和異常產(chǎn)生的代碼,可以很容易的得到對(duì)象圖形的XML表示。根元素<customer>代表Customer對(duì)象,它包括所有的屬性(一個(gè)家庭地址,兩個(gè)發(fā)貨地址,一個(gè)ID,一個(gè)電話(huà)號(hào)碼等)。

    定制XML文檔 

    音樂(lè)公司和他的商業(yè)伙伴對(duì)上面給出的XML文檔(Listing 2)并不完全滿(mǎn)意,他們可能拋棄某些信息(地址標(biāo)識(shí)符號(hào),tags)出生日期的格式,訂單的某些屬性等。由于有了javax.xml.bind.annotation包的注釋?zhuān)琂AXB提供了一種方式來(lái)定制和控制XML的結(jié)構(gòu)。 

    首先,如果你想拋棄<customer>元素而使用<individual>或者<company>來(lái)替代根元素。如果讓JAXB不使用抽象Customer類(lèi),可以放棄使用@XmlRootElement而使用@XmlTransient來(lái)產(chǎn)生臨時(shí)類(lèi)。

 
      XML文檔是由一系列的元素(<element>value</element>)和屬性(<element attribute="value"/>)組成。JAXB使用兩種注釋來(lái)區(qū)分他們:@XmlAttribute 和 @XmlElement,每個(gè)注釋有一系列的參數(shù)可以對(duì)屬性進(jìn)行重命名,可以為空值,給定的一個(gè)默認(rèn)值等。下列代碼使用兩種注釋來(lái)將id轉(zhuǎn)換為XMl的屬性(而不是元素)并且重命名了發(fā)貨地址元素(將address改為deliveryAddress):
@XmlTransient public abstract class Customer { @XmlAttribute protected Long id; protected String telephone; protected String email; protected Address homeAddress; @XmlElementWrapper(name = "delivery") @XmlElement(name = "address") protected List<Address> deliveryAddresses = new ArrayList<Address>(); // Constructors, getters, setters }
    這段代碼使用了@XmlElementWrapper注釋?zhuān)a(chǎn)生包裝元素在發(fā)貨地址的外圍。再看Listing 2,有個(gè)<deliveryAddresses>元素,通過(guò)上面的代碼,就可以在<address>元素前加了<delivery>元素。 

    繼續(xù)討論地址,如果想要放棄標(biāo)識(shí)符和tags,可以使用@XmlTransient注釋。為了重命名一個(gè)元素,使用@XmlElement注釋的name屬性。下列代碼就對(duì)屬性zipcode重命名為<zip>元素:
@XmlType(propOrder = {"street", "zipcode", "city", "country"}) @XmlAccessorType(XmlAccessType.FIELD) public class Address { @XmlTransient private Long id; private String street; private String city; @XmlElement(name = "zip") private String zipcode; private String country; @XmlTransient private List<Tag> tags = new ArrayList<Tag>(); // Constructors, getters, setters }
    上面的@XmlType注釋可以將一個(gè)類(lèi)或者枚舉映射為一個(gè)XML schema類(lèi)型??梢允褂盟鼇?lái)指定一個(gè)命名空間或者使用propOrder屬性來(lái)定制屬性,按照這個(gè)定制可以列出屬性的名字和產(chǎn)生XML文檔。 

    Table 1顯示了XML文檔的三個(gè)不同的摘錄:

Default XML Representation

 

 

 

 

 

Annotated Customer Class

 

 

 

 

 

Annotated Address Class

 

 

 

 

 

<customer>
  <deliveryAddresses>
    <city>London</city>
    <country>UK</country>
    <id>3</id>
    <street>Findsbury</street>
    <tags>
      <name>working hours</name>
    </tags>
    <tags>
      <name>mind the dog</name>
    </tags>
    <zipcode>CE451</zipcode>
  </deliveryAddresses>
  <deliveryAddresses>
    <city>Brighton</city>
    <country>UK</country>
    <id>4</id>
    <street>Camden</street>
    <tags>
      <name>working hours</name>
    </tags>
    <tags>
      <name>week-ends</name>
    </tags>
    <zipcode>NW487</zipcode>
  </deliveryAddresses>
  (...)
</customer>

 

 

 

 

 

<individual id="1">
  <delivery>
    <address>
      <city>London</city>
      <country>UK</country>
      <id>3</id>
      <street>Findsbury</street>
      <tags>
        <name>working hours</name>
      </tags>
      <tags>
        <name>mind the dog</name>
      </tags>
      <zipcode>CE451</zipcode>
    </address>
    <address>
      <city>Brighton</city>
      <country>UK</country>
      <id>4</id>
      <street>Camden</street>
      <tags>
        <name>working hours</name>
      </tags>
      <tags>
        <name>week-ends</name>
      </tags>
      <zipcode>NW487</zipcode>
    </address>
  </delivery>
  (...)
</individual>

 

 

 

 

 

<individual id="1">
  <delivery>
   <address>
     <street>Findsbury</street>
     <zip>CE451</zip>
     <city>London</city>
     <country>UK</country>
   </address>
   <address>
     <street>Camden</street>
     <zip>NW487</zip>
     <city>Brighton</city>
     <country>UK</country>
   </address>
  </delivery>
  (...)
</individual>

 

 

 

 

 


    也可以注釋具體的類(lèi)Company和Individual來(lái)定制映射。首先作為XML文檔的根元素,不得不使用@XmlRootElement注釋來(lái)指定XML命名空間http://www.watermelon.example/customer。該例子中使用@XmlType.propOrder來(lái)定制屬性??梢允褂脧某?lèi)Customer中繼承像id,email,telephone,homeAddress等。

Annotated Company Class

 

 

 

 

 

Annotated Individual Class

 

 

 

 

 

@XmlRootElement(name = "company", namespace=

"http://www.watermelon.example/customer")
@XmlType(propOrder = {"id", "name", "contactName",
        "telephone", "email", "numberOfEmployees",
        "homeAddress", "deliveryAddresses"})
@XmlAccessorType(XmlAccessType.FIELD)
public class Company extends Customer {

  @XmlAttribute
  private String name;
  private String contactName;
  private Integer numberOfEmployees;
  // Constructors, getters, setters
}

 

 

 

 

 

@XmlRootElement(name = "individual", namespace = 
"http://www.watermelon.example/customer")
@XmlType(propOrder = {"id", "lastname",
         "firstname", "dateOfBirth", "telephone",
         "email", "homeAddress",
         "deliveryAddresses"})
@XmlAccessorType(XmlAccessType.FIELD)
public class Individual extends Customer {

  private String firstname;
  @XmlAttribute
  private String lastname;
  @XmlJavaTypeAdapter(DateAdapter.class)
  private Date dateOfBirth;
  // Constructors, getters, setters
}

 

 

 

 

 

      JAXB映射java.util.Date屬性為默認(rèn)值,例如,個(gè)體的出生日期將顯示為下列格式:<dateOfBirth>1940-08-07T00:00:00.781+02:00</dateOfBirth> 

      為了格式化日期(如:07/08/1953),有兩種選擇: 
      1. 使用日期類(lèi)型javax.xml.datatype.XMLGregorianCalendar而不使用java.util.Date。 
      2. 使用一個(gè)適配器,就像上面代碼看到的那樣,個(gè)體類(lèi)Individual使用@XmlJavaTypeAdapter注釋。@XmlJavaTypeAdapter(DateAdapter.class)通知JAXB使用適配器調(diào)用DateAdapter當(dāng)marshalling/unmarshalling屬性dateOfBirth時(shí)。 

      寫(xiě)一個(gè)類(lèi)(DateAdapter)來(lái)繼承XmlAdapter。覆蓋marshal 和 unmarshal方法。這種方法可以將日期按照一定格式的字符串進(jìn)行格式化,反之亦然。下列代碼使用java.text.SimpleDateFormat來(lái)格式化日期:
public class DateAdapter extends XmlAdapter<String, Date> { DateFormat df = new SimpleDateFormat("dd/MM/yyyy"); public Date unmarshal(String date) throws Exception { return df.parse(date); } public String marshal(Date date) throws Exception { return df.format(date); } }
      現(xiàn)在返回Listing 1,如果Marshaller.marshal()方法被調(diào)用,DateAdapter.marshal()也被調(diào)用,出生日期也被格式化了.下面是獲得的XML文檔:

Individual XML Document

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:individual lastname="Starr" id="1" xmlns:ns2="http://www.watermelon.example/customer">
    <firstname>Ringo</firstname>
    <dateOfBirth>07/08/1940</dateOfBirth>
    <telephone>+187445</telephone>
    <email>ringo@star.co.uk</email>
    <homeAddress>
        <street>Abbey Road</street>
        <zip>SW14</zip>
        <city>London</city>
        <country>UK</country>
    </homeAddress>
    <delivery>
        <address>
            <street>Findsbury Avenue</street>
            <zip>CE451</zip>
            <city>London</city>
            <country>UK</country>
        </address>
        <address>
            <street>Camden Street</street>
            <zip>NW487</zip>
            <city>Brighton</city>
            <country>UK</country>
        </address>
    </delivery>
</ns2:individual>

Company XML Document

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:company name="Sony" id="1" xmlns:ns2="http://www.watermelon.example/customer">
    <contactName>Mr Father</contactName>
    <telephone>+14519454</telephone>
    <email>contact@sony.com</email>
    <numberOfEmployees>25000</numberOfEmployees>
    <homeAddress>
        <street>General Alley</street>
        <zip>75011</zip>
        <city>Paris</city>
        <country>FR</country>
    </homeAddress>
    <delivery>
        <address>
            <street>St James St</street>
            <zip>SW14</zip>
            <city>London</city>
            <country>UK</country>
        </address>
        <address>
            <street>Central Side Park</street>
            <zip>7845</zip>
            <city>New York</city>
            <country>US</country>
        </address>
    </delivery>
</ns2:company>


     Unmarshal和產(chǎn)生Schema 
     如圖1所示,JAXB可以用來(lái)unmarshal,產(chǎn)生和編譯一個(gè)schema,也就是用先前獲得的XML文檔來(lái)產(chǎn)生對(duì)象圖表。首先得到一個(gè)JAXBContext,創(chuàng)建一個(gè)Unmarshaller對(duì)象,調(diào)用unmarshal方法,然后返回Individual的屬性及他的一個(gè)實(shí)例:
// xmlString contains the XML document of an individual StringReader reader = new StringReader(xmlString); JAXBContext context = JAXBContext.newInstance(Individual.class); Unmarshaller u = context.createUnmarshaller(); Individual individual = (Individual) u.unmarshal(reader); System.out.println(individual.getFirstname());
     一個(gè)XML schema描述了XML文檔的結(jié)構(gòu),用XML語(yǔ)法來(lái)寫(xiě)的。如果你對(duì)XML schema了解的不多,你也可以使用Sun的JAXB實(shí)現(xiàn)提供的schemaGen工具來(lái)產(chǎn)生一個(gè)XML schema。如Listing 3,可以看到Address, Company, Individual和 Tag類(lèi)被描述為復(fù)雜的類(lèi)型:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <xs:schema version="1.0" xmlns:xs="http://www./2001/XMLSchema"> <xs:complexType name="address"> <xs:sequence> <xs:element name="street" type="xs:string" minOccurs="0"/> <xs:element name="zip" type="xs:string" minOccurs="0"/> <xs:element name="city" type="xs:string" minOccurs="0"/> <xs:element name="country" type="xs:string" minOccurs="0"/> </xs:sequence> </xs:complexType> <xs:complexType name="company"> <xs:sequence> <xs:element name="contactName" type="xs:string" minOccurs="0"/> <xs:element name="telephone" type="xs:string" minOccurs="0"/> <xs:element name="email" type="xs:string" minOccurs="0"/> <xs:element name="numberOfEmployees" type="xs:int" minOccurs="0"/> <xs:element name="homeAddress" type="address" minOccurs="0"/> <xs:element name="delivery" minOccurs="0"> <xs:complexType> <xs:sequence> <xs:element name="address" type="address" minOccurs="0" maxOccurs="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute name="id" type="xs:long"/> <xs:attribute name="name" type="xs:string"/> </xs:complexType> <xs:complexType name="individual"> <xs:sequence> <xs:element name="firstname" type="xs:string" minOccurs="0"/> <xs:element name="dateOfBirth" type="xs:string" minOccurs="0"/> <xs:element name="telephone" type="xs:string" minOccurs="0"/> <xs:element name="email" type="xs:string" minOccurs="0"/> <xs:element name="homeAddress" type="address" minOccurs="0"/> <xs:element name="delivery" minOccurs="0"> <xs:complexType> <xs:sequence> <xs:element name="address" type="address" minOccurs="0"
maxOccurs
="unbounded"/> </xs:sequence> </xs:complexType> </xs:element> </xs:sequence> <xs:attribute name="id" type="xs:long"/> <xs:attribute name="lastname" type="xs:string"/> </xs:complexType> <xs:complexType name="tag"> <xs:sequence> <xs:element name="addresses" type="address" nillable="true"
minOccurs
="0" maxOccurs="unbounded"/> <xs:element name="name" type="xs:string" minOccurs="0"/> </xs:sequence> </xs:complexType> <xs:complexType name="dateAdapter"> <xs:complexContent> <xs:extension base="xmlAdapter"> <xs:sequence/> </xs:extension> </xs:complexContent> </xs:complexType> <xs:complexType name="xmlAdapter" abstract="true"> <xs:sequence/> </xs:complexType> </xs:schema>
     如果下載JAXB,schema編譯器(xjc)也會(huì)被一同下載。
     持久化注釋 
     如果你認(rèn)為JAXB可以將數(shù)據(jù)持久化到XML。JPA則是和它差不多的關(guān)系數(shù)據(jù)庫(kù)的術(shù)語(yǔ),事實(shí)上,二者都是依靠的注釋?zhuān)@就意味著同樣的類(lèi)都可以被JPA和JAXB注釋?zhuān)凑者@種說(shuō)法,可以提供一個(gè)XML表示也當(dāng)然也可以被持久化到一個(gè)數(shù)據(jù)庫(kù)。 

     下面是Address類(lèi):
@Entity @Table(name = "t_address") @XmlType(propOrder = {"street", "zipcode", "city", "country"}) @XmlAccessorType(XmlAccessType.FIELD) public class Address { @XmlTransient @Id @GeneratedValue private Long id; private String street; @Column(length = 100) private String city; @Column(name = "zip_code", length = 10) @XmlElement(name = "zip") private String zipcode; @Column(length = 50) private String country; @XmlTransient @ManyToMany(cascade = CascadeType.PERSIST) @JoinTable(name = "t_address_tag", joinColumns = {@JoinColumn(name = "address_fk")}, inverseJoinColumns = {@JoinColumn(name = "tag_fk")}) private List<Tag> tags = new ArrayList<Tag>(); // Constructors, getters, setters }
( 完 )

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀(guān)點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多