论坛首页 Java企业应用论坛

从一个实例看jaxb的强大

浏览 41820 次
该帖已经被评为良好帖
作者 正文
   发表时间:2006-11-11  
SOA
   读取xml对于应用软件来说是一个必不可少的工作,当然现在的jdk也提供了很好的处理xml方式,读写xml的库也挺多,包括有名的dom4j,不管使用任何的代码库,对于xml只是一个解析工作而已,不能马上绑定到java 对象。对于对象,每次都需要set 或者get相应的属性,当然也可以使用map 来保存xml配置。
    于是,一种新的处理方式用于对象和xml之间的映射就变得非常需要,还好sun提供了jaxb,一种很方便的方式来处理java对象和xml内容。下面通过一个实例来体会一下。
    看一下如下的xml
<?xml version="1.0"?>
<customer id="No1">
    <name>Alice Smith</name>
    <address>
        <street>123 Maple Street</street>
        <city>Cambridge</city>
        <zip>12345</zip>
    </address>
</customer>

别忘了生成相应的xsd,或者dtd文件,这是主要的配置:
xsd:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  
    <xs:complexType name="Customer">
      <xs:sequence>
         <xs:element name="address" type="Address"/>
         <xs:element name="name" type="xs:string"/>
      </xs:sequence>
       <xs:attribute name="id" type="xs:string"/>      
    </xs:complexType>
  
      <xs:complexType name="Address">
      <xs:sequence>
         <xs:element name="street" type="xs:string"/>
         <xs:element name="city" type="xs:string"/>
         <xs:element name="zip" type="ZipCodeType"/>
       </xs:sequence>
   </xs:complexType>
 
    <xs:simpleType name="ZipCodeType">
      <xs:restriction base="xs:integer">
         <xs:minInclusive value="10000"/>
         <xs:maxInclusive value="99999"/>
      </xs:restriction>
    </xs:simpleType>
    <xs:element name="customer" type="Customer"/>
    <xs:element name="address" type="Address"/>
</xs:schema>


需要映射两个java对象,CustomerBo和AddressBo
java 对象可以通过xjc来生成。
或者自己定义(但需要增加相应的java注释,如@XmlAccessorType,@XmlType,这是给引擎使用的)
所以一般通过xjd自动生成


@XmlAccessorType(AccessType.FIELD)
@XmlType(name = "Customer", propOrder = {
    "address",
    "customerName"
})
public class CustomerBo {

    protected Address address;

    @XmlElement(name = "name")
    protected String customerName;

    @XmlAttribute
    protected String id;

    public Address getAddress() {
        return address;
    }

    public String getCustomerName() {
        return customerName;
    }

    public String getId() {
        return id;
    }

    public void setAddress(Address value) {
        this.address = value;
    }

    public void setCustomerName(String value) {
        this.customerName = value;
    }

    public void setId(String value) {
        this.id = value;
    }
}


public class Address {

    protected String street;

    protected String city;

    @XmlElement(name = "zip")
    protected BigInteger zipCode;

    public String getStreet() {
        return street;
    }

    public void setStreet(String value) {
        this.street = value;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String value) {
        this.city = value;
    }

    public BigInteger getZipCode() {
        return zipCode;
    }

    public void setZipCode(BigInteger value) {
        this.zipCode = value;
    }

}

定义jxb绑定文件:
<jxb:bindings version="1.0"
               xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
               xmlns:xs="http://www.w3.org/2001/XMLSchema">
   <jxb:bindings schemaLocation="customer.xsd" node="/xs:schema">  
         
   <jxb:globalBindings
         fixedAttributeAsConstantProperty="false"
         collectionType="java.util.Vector"
         typesafeEnumBase="xs:NCName"
         choiceContentProperty="false"
         typesafeEnumMemberName="generateError"
         enableFailFastCheck="false" 
         generateIsSetMethod="false"
         underscoreBinding="asCharInWord"/>
   <jxb:schemaBindings>
      <jxb:package name="mycompany.demo">
        <jxb:javadoc><![CDATA[<body>Package level documentation for generated package mycompany.demo.</body>]]>
        </jxb:javadoc>
      </jxb:package>
      <jxb:nameXmlTransform>
        <jxb:elementName suffix="Element"/>
      </jxb:nameXmlTransform>
    </jxb:schemaBindings> 

    //需要绑定的元素
   <jxb:bindings node="//xs:complexType[@name='Customer']">
       //绑定的类
      <jxb:class name="CustomerBo">
        <jxb:javadoc>A &lt;b>todo..</jxb:javadoc>
      </jxb:class>
      <jxb:bindings node=".//xs:element[@name='name']">
           //绑定的属性
           <jxb:property name="customerName"/>
        </jxb:bindings>
    </jxb:bindings> 
        
    <jxb:bindings node="//xs:complexType[@name='Address']">
      <jxb:class name="AddressBo">
        <jxb:javadoc><![CDATA[First line of documentation for a <b>Address</b>.]]></jxb:javadoc>
      </jxb:class>
      <jxb:bindings node=".//xs:element[@name='zip']">
         <jxb:property name="zipCode"/>
      </jxb:bindings>
    </jxb:bindings>
           
   </jxb:bindings>
</jxb:bindings>

    看着比较复杂,其实挺好理解,当然可以不需要这个绑定文件,也可以绑定相应的java 类,但需要元素名称和类名称完全一致,而且属性也要一致。

    看一下jaxb是如何来读入xml的:
        //主要的环境类,主要读取ObjectFactory这个类,这是由xjc生成的。
        JAXBContext jc = JAXBContext.newInstance("mycompany.demo");
        Unmarshaller u = jc.createUnmarshaller();
        JAXBElement customerE = (JAXBElement) u.unmarshal(new FileInputStream(
                                "customer.xml"));
        CustomerBo bo = (CustomerBo) customerE.getValue();
    就是这么简单

    写入也比较简单:
        JAXBContext jc = JAXBContext.newInstance("mycompany.demo");
        Marshaller marshaller=jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        customerE.setValue(bo);
        marshaller.marshal( customerE,new FileOutputStream("test.xml"));
 
    在webservices中jaxb的作用是明显的,当然也有不方便的地方,比如定义binding.jaxb文件时,如果没有工具支持,手工写,还是比较困难。
   发表时间:2006-11-13  
看起来好麻烦啊!简单用途的话XStream就可以了
0 请登录后投票
   发表时间:2006-11-13  
贴个xstream的:)
public class Customer {

	protected Address address;

	protected String name;

	protected String id;
	
	public String toString(){
		return id+ " " + name + "@" + address;
	}
}

import java.math.BigInteger;

public class Address {

	protected String street;

	protected String city;

	protected BigInteger zip;

	public String toString(){
		return city+ " " + street + " " + zip;
	}
}


import java.io.InputStream;

import com.thoughtworks.xstream.XStream;

public class XStreamDataReader {

        public static void main(String[] args) {
   	
            XStream xstream = new XStream();
            xstream.alias("customer", Customer.class);
            xstream.alias("address", Address.class);
            
            xstream.useAttributeFor("id", String.class);
            
            InputStream in = XStreamDataReader.class.getResourceAsStream("data.xml");
            Customer bo = (Customer)xstream.fromXML(in);
            
			System.out.println(bo);

            xstream.toXML(bo,    new FileWriter("data1.xml"));//另存为...
        }
}
0 请登录后投票
   发表时间:2006-11-14  
一直用JiBX,觉得很好用,只要xml文件配置一下就ok了

0 请登录后投票
   发表时间:2006-11-14  
看了楼主的文章,受益了, 不过还是有两个问题
-------------------------------
需要映射两个java对象,CustomerBo和AddressBo
java 对象可以通过xjc来生成。
或者自己定义(但需要增加相应的java注释,如@XmlAccessorType,@XmlType,这是给引擎使用的)
所以一般通过xjd自动生成

一个java对像要用两种工具生成吗,是什么工具,能不能告诉我全名啊,。

---------------------------------------
别忘了生成相应的xsd,或者dtd文件,
这个东东要用什么东东成生,

---------------------------------------
JAXBContext jc = JAXBContext.newInstance("mycompany.demo");
mycompany.demo是什么东东
0 请登录后投票
   发表时间:2006-11-14  
xmx0632 写道
贴个xstream的:)
public class XStreamDateReader {
InputStream in = XStreamDateReader.class.getResourceAsStream("data.xml");

大哥,你手真快!。。。上面的DateReader应该是DataReader吧
0 请登录后投票
   发表时间:2006-11-14  
以前自己写,后来用过apache的betwixt,感觉比这里说的jaxb简单的多。
0 请登录后投票
   发表时间:2006-11-14  
以前自己写,后来用过apache的betwixt,感觉比这里说的jaxb简单的多。
0 请登录后投票
   发表时间:2006-11-14  
不好意思,我这里FCKeditor出错,连发了2次
0 请登录后投票
   发表时间:2006-11-15  
想不到有那么多人关注,我只是在学习jaxb当中,有几点需要说明一下:
  
   jaxb,不只是一个单纯的工具库,感觉功能比较强大,需要和其他的jaxp相互协作。
   jaxb关注的方面更广,能处理更为复杂的xml,

看一下以下代码就可以知道:
   代码1,处理xpath
   JAXBXpath jaxbXpath = new JAXBXpath(doc, binder);
   (USAddress) jaxbXpath.evaluate("/purchaseOrder/shipTo");
 
   代码2,直接更新xml
   Binder<Node> binder=JAXBContext.createBinder()
   JAXBElement<Items.Item> itemE = binder.unmarshal(
                    node,
                    Items.Item.class);
   binder.Items.Item item = itemE.getValue();
   item.setComment("qualifies for free shipping");
    binder.updateXML(item);

当然为了处理复杂的xml,其复杂的配置也是不可少的。

xstream 我也了解过,不过大多数情况下我只是用来作为java Serializable 而使用。
对于处理一些比较简单的xml,xstream 是比较方便。

感觉两者的目的不太一致。有兴趣的可以去看看sun的jwsdp带的相关例子


0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics