zoukankan      html  css  js  c++  java
  • Jaxb 完全手册

    Jaxb是JavaEE的规范.全称Java Architecture for XML Binding. 
    可以根据XML Schema产生Java类的技术.JAXB也提供了将XML实例文档反向生成Java对象树的方法,并能将Java对象树的内容重新写到XML实例文档. 
    JAXB 2.0是JDK 1.6的组成部分。JAXB 2.2.3是JDK 1.7的组成部分。在实际使用不需要引入新的jar. 
    我一般使用都是配合JPA使用,下面例子也是按JPA+JAXB来说明. 
    因此我需要引入jpa的实现包.hibernate-validator随便.做验证用的.

    <dependency>
        <groupId>org.hibernate.javax.persistence</groupId>
        <artifactId>hibernate-jpa-2.0-api</artifactId>
        <version>1.0.1.Final</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>5.0.1.Final</version>
    </dependency>

    1. JDK中JAXB相关的重要Class和Interface:

    • JAXBContext类,是应用的入口,用于管理XML/Java绑定信息。
    • Marshaller接口,将Java对象序列化为XML数据。
    • Unmarshaller接口,将XML数据反序列化为Java对象。

    http://my.oschina.net/zhaoqian/blog/89763 这个是简单的入门demo.可以先运行试试,对JAXB有个大概的使用方法.下面例子将是系统正常做的.并对并发性进行处理的一个例子.

    2. 常用注解说明

    常用的annotation有:
    @XmlType
    @XmlElement
    @XmlRootElement
    @XmlAttribute
    @XmlAccessorType
    @XmlAccessorOrder
    @XmlTransient
    @XmlJavaTypeAdapter
    @Temporal(TemporalType.XXXX) -->JPA中的时间处理注解,非JAXB
    @XmlElementWrapper

    1.@XmlType
      @XmlType用在class类的注解,常与@XmlRootElement,@XmlAccessorType一起使用。它有三个属性:name、propOrder、namespace,经常使用的只有前两个属性。如:
    同时使用了@XmlType(propOrder={})和@XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL)的时候,生成的xml只按照propOrder定义的顺序生成元素
    @XmlType(name = "basicStruct", propOrder = {
        "intValue",
        "stringArray",
        "stringValue"
    )
    在使用@XmlType的propOrder 属性时,必须列出JavaBean对象中的所有属性,否则会报错。

    2.@XmlRootElement
      @XmlRootElement用于类级别的注解,对应xml的跟元素,常与 @XmlType 和 @XmlAccessorType一起使用。如:
      @XmlType
      @XmlAccessorType(XmlAccessType.FIELD)
      @XmlRootElement
      public class Address {}

    3.@XmlElement
      @XmlElement将java对象的属性映射为xml的节点,在使用@XmlElement时,可通过name属性改变java对象属性在xml中显示的名称。如:
      @XmlElement(name="Address")  
      private String yourAddress;

    4.@XmlAttribute
      @XmlAttribute用于把java对象的属性映射为xml的属性,并可通过name属性为生成的xml属性指定别名。如:
      @XmlAttribute(name="Country")
      private String state;
     
    5.@XmlAccessorType
      @XmlAccessorType用于指定由java对象生成xml文件时对java对象属性的访问方式。常与@XmlRootElement、@XmlType一起使用。它的属性值是XmlAccessType的4个枚举值,分别为:

    • XmlAccessType.FIELD:java对象中的所有成员变量
    • XmlAccessType.PROPERTY:java对象中所有通过getter/setter方式访问的成员变量
    • XmlAccessType.PUBLIC_MEMBER:java对象中所有的public访问权限的成员变量和通过getter/setter方式访问的成员变量
    • XmlAccessType.NONE:java对象的所有属性都不映射为xml的元素

    注意:@XmlAccessorType的默认访问级别是XmlAccessType.PUBLIC_MEMBER,因此,如果java对象中的private成员变量设置了public权限的getter/setter方法,就不要在private变量上使用@XmlElement和@XmlAttribute注解,否则在由java对象生成xml时会报同一个属性在java类里存在两次的错误。同理,如果@XmlAccessorType的访问权限为XmlAccessType.NONE,如果在java的成员变量上使用了@XmlElement或@XmlAttribute注解,这些成员变量依然可以映射到xml文件。

    注意:虽然@XmlAccessorType为XmlAccessType.NONE,但是在java类的私有属性上加了@XmlAttribute和@XmlElement注解后,这些私有成员会映射生成xml的元素

    6.@XmlAccessorOrder
      @XmlAccessorOrder用于对java对象生成的xml元素进行排序。它有两个属性值:
      AccessorOrder.ALPHABETICAL:对生成的xml元素按字母书序排序
      XmlAccessOrder.UNDEFINED:不排序

    7.@XmlTransient
      @XmlTransient用于标示在由java对象映射xml时,忽略此属性。即,在生成的xml文件中不出现此元素。

    8.@XmlJavaTypeAdapter
      @XmlJavaTypeAdapter常用在转换比较复杂的对象时,如map类型或者格式化日期等。使用此注解时,需要自己写一个adapter类继承XmlAdapter抽象类,并实现里面的方法。
      @XmlJavaTypeAdapter(value=xxx.class),value为自己定义的adapter类
      XmlAdapter 抽象接口如下:

    public abstract class XmlAdapter<ValueType,BoundType> {    // Do-nothing constructor for the derived classes.
        protected XmlAdapter() {}
        // Convert a value type to a bound type.
        public abstract BoundType unmarshal(ValueType v);
        // Convert a bound type to a value type.
        public abstract ValueType marshal(BoundType v);
     }

    实际案例:

    <i>package jaxb.shop;
      
    import java.util.Date;
    import java.text.SimpleDateFormat;
      
    import javax.xml.bind.annotation.adapters.XmlAdapter;
      
    public class DateAdapter extends XmlAdapter<String, Date> {
      
        private String pattern = "yyyy-MM-dd HH:mm:ss";
        SimpleDateFormat fmt = new SimpleDateFormat(pattern);
          
        @Override
        public Date unmarshal(String dateStr) throws Exception {
              
            return fmt.parse(dateStr);
        }
      
        @Override
        public String marshal(Date date) throws Exception {
              
            return fmt.format(date);
        }
      
    }
    //用于格式化日期在xml中的显示格式,并且由xml unmarshal为java对象时,将字符串解析为Date对象</i>

    在某个类中如下使用,解析出对应的时间格式.必须重载那2个方法,用于JAXB marshal xml,xml unmarshal object时候使用.

       @XmlJavaTypeAdapter(value=DateAdapter.class)
        private Date purDate;

    9.但如果是和JPA一起使用的话,可以使用@Temporal(TemporalType.DATE)来格式时间,默认为TemporalType.TIMESTAMP类型.TemporalType属性如下:
    public enum TemporalType {
        DATE, //java.sql.Date
        TIME, //java.sql.Time
        TIMESTAMP //java.sql.Timestamp
    }
    java.sql.Date
    日期型,精确到年月日,例如“2008-08-08”
    java.sql.Time
    时间型,精确到时分秒,例如“20:00:00”
    java.sql.Timestamp
    时间戳,精确到纳秒,例如“2008-08-08 20:00:00.000000001”

    10.在JAXB标准中,@XmlElementWrapper注解表示生成一个包装 XML 表示形式的包装器元素。 此元素主要用于生成一个包装集合的包装器 XML 元素。
    注:@XmlElementWrapper仅允许出现在集合属性上。最后的案例将使用这个注解.

    3. 最终案例(模拟XML--系统 --DB)

    例子XML示例.

    <?xml version="1.0" encoding="utf-8"?>
    <userinfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <id>110</id>
        <name>Credo</name>
        <address>China BeiJing</address>
        <job>programmer</job>
        <overinfos>
            <overinfo>
                <hobby>Accompany my girlfriend.</hobby>
                <!--开始日期 dateTime-->
                <beginDate>2009-06-02T12:00:00</beginDate>
                <!--结束日期 dateTime-->
                <endDate>2109-06-02T12:00:00</endDate>
            </overinfo>
            <overinfo>
                <hobby>Write some code.</hobby>
                <!--开始日期 dateTime-->
                <beginDate>2009-06-02T12:00:00</beginDate>
                <!--结束日期 dateTime-->
                <endDate>2029-06-02T12:00:00</endDate>
            </overinfo>
        </overinfos>
    </userinfo>

    Model层(JAXB+JPA):

    package org.credo.jaxb.model;
    import java.io.Serializable;
    import java.util.List;
    import javax.persistence.CascadeType;
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.OneToMany;
    import javax.persistence.Table;
    import javax.xml.bind.annotation.XmlAccessType;
    import javax.xml.bind.annotation.XmlAccessorType;
    import javax.xml.bind.annotation.XmlElement;
    import javax.xml.bind.annotation.XmlElementWrapper;
    import javax.xml.bind.annotation.XmlElements;
    import javax.xml.bind.annotation.XmlRootElement;
    import org.hibernate.validator.constraints.Length;
    /**
     * @author Credo
     */
    @XmlRootElement
    @XmlAccessorType(XmlAccessType.FIELD)
    @Entity
    @Table(name = "USERINFO")
    public class Userinfo implements Serializable{
         
        private static final long serialVersionUID = 7870351249722416047L;
         
        @Id
        @Column(name = "ID", nullable = false)
        private Long id;
         
        @Column(name = "NAME", length = 50)
        @Length(max = 50)
        private String name;
         
        @Column(name = "ADDRESS", length = 50)
        @Length(max = 50)
        private String address;
         
        @Column(name = "JOB", length = 50)
        @Length(max = 50)
        private String job;
         
        @XmlElementWrapper(name = "overinfos")
        @OneToMany(cascade = CascadeType.ALL)
        @XmlElements(value = { @XmlElement(name = "overinfo", type = Overinfo.class) })
        private List<Overinfo> overinfos;
         
        public Long getId() {
            return id;
        }
        public void setId(Long id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public String getAddress() {
            return address;
        }
        public void setAddress(String address) {
            this.address = address;
        }
        public String getJob() {
            return job;
        }
        public void setJob(String job) {
            this.job = job;
        }
        public List<Overinfo> getOverinfos() {
            return overinfos;
        }
        public void setOverinfos(List<Overinfo> overinfos) {
            this.overinfos = overinfos;
        }
         
    }

    Overinfo.class

    package org.credo.jaxb.model;
    import java.io.Serializable;
    import java.util.Date;
    import javax.persistence.CascadeType;
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.GeneratedValue;
    import javax.persistence.GenerationType;
    import javax.persistence.Id;
    import javax.persistence.JoinColumn;
    import javax.persistence.ManyToOne;
    import javax.persistence.Table;
    import javax.persistence.Temporal;
    import javax.persistence.TemporalType;
    import javax.xml.bind.annotation.XmlAccessType;
    import javax.xml.bind.annotation.XmlAccessorType;
    import javax.xml.bind.annotation.XmlTransient;
    import javax.xml.bind.annotation.XmlType;
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "overinfo")
    @Entity
    @Table(name = "OVERINFO")
    public class Overinfo implements Serializable {
        private static final long serialVersionUID = 2579971237985854291L;
        @XmlTransient
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "ID")
        private Long id;
         
        @XmlTransient
        @ManyToOne(cascade = CascadeType.ALL)
        @JoinColumn(name = "UserinfoId")
        private Userinfo userinfo;
         
        @Column(name = "hobby", length = 20)
        private String hobby;
         
        @Temporal(TemporalType.DATE)
        @Column(name = "beginDate", length = 20)
        private Date beginDate;
         
        @Temporal(TemporalType.DATE)
        @Column(name = "endDate", length = 20)
        private Date endDate;
        public String getHobby() {
            return hobby;
        }
        public void setHobby(String hobby) {
            this.hobby = hobby;
        }
        public Date getBeginDate() {
            return beginDate;
        }
        public void setBeginDate(Date beginDate) {
            this.beginDate = beginDate;
        }
        public Date getEndDate() {
            return endDate;
        }
        public void setEndDate(Date endDate) {
            this.endDate = endDate;
        }
        public Long getId() {
            return id;
        }
        public void setId(Long id) {
            this.id = id;
        }
        public Userinfo getUserinfo() {
            return userinfo;
        }
        public void setUserinfo(Userinfo userinfo) {
            this.userinfo = userinfo;
        }
    }

    JAXB并发处理:

    package org.credo.jaxb;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.ConcurrentMap;
    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.JAXBException;
    public final class JAXBCache {
        private static final JAXBCache instance = new JAXBCache();
        private final ConcurrentMap<String, JAXBContext> contextCache = new ConcurrentHashMap<String, JAXBContext>();
        private JAXBCache() {
        }
        public static JAXBCache instance() {
            return instance;
        }
        JAXBContext getJAXBContext(Class<?> clazz) throws JAXBException {
            JAXBContext context = contextCache.get(clazz.getName());
            if ( context == null )
            {
                context = JAXBContext.newInstance(clazz);
                contextCache.putIfAbsent(clazz.getName(), context);
            }
            return context;
        }
    }

    JAXBExportSchema 导出JAXB的 class的 结构

    package org.credo.jaxb;
    import java.io.File;
    import java.io.IOException;
    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.SchemaOutputResolver;
    import javax.xml.transform.Result;
    import javax.xml.transform.stream.StreamResult;
    import org.credo.jaxb.model.Userinfo;
    /**
     * JAXB 导出Schema。
     *
     * @author: Credo
     * @date: 2013-6-25
     */
    public class JAXBExportSchema {
        public static void main(String[] args) {
            JAXBContext jct;
            try
            {
                jct = JAXBContext.newInstance(Userinfo.class);
                jct.generateSchema(new Resolver());
            }
            catch ( Exception ex )
            {
                ex.printStackTrace();
            }
        }
    }
    class Resolver extends SchemaOutputResolver {
        @Override
        public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException {
            File file = new File("d:\", suggestedFileName);
            StreamResult result = new StreamResult(file);
            result.setSystemId(file.toURI().toURL().toString());
            return result;
        }
    }

    JAXBUtil以及main方法测试:

    package org.credo.jaxb;
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.List;
    import javax.xml.bind.JAXBContext;
    import javax.xml.bind.JAXBException;
    import javax.xml.bind.Marshaller;
    import javax.xml.bind.Unmarshaller;
    import org.apache.commons.io.IOUtils;
    import org.credo.jaxb.model.Overinfo;
    import org.credo.jaxb.model.Userinfo;
    /**
     * marshal对象和unmarshal对象都是由JAXBContext创建.所以一开始需要初始化JAXBContext.
     * @author Credo
     */
    public class JAXBUtil {
        /**
         * 生成xml文件的二进制数据
         * @param obj 对象
         */
        public static byte[] marshal(Object obj) throws JAXBException {
            JAXBContext context = JAXBCache.instance().getJAXBContext(obj.getClass());
            Marshaller m = context.createMarshaller();
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
            m.marshal(obj, outputStream);
            byte[] result = outputStream.toByteArray();
            return result;
        }
        /**
         * @param data xml stream
         * @param classe 类
         * @return jaxb生成xml的java 类对象
         */
        public static Object unmarshal(byte[] data, Class<?> classe) throws JAXBException {
            JAXBContext context = JAXBCache.instance().getJAXBContext(classe);
            Unmarshaller m = context.createUnmarshaller();
            ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
            Object obj = m.unmarshal(inputStream);
            return obj;
        }
        /**
         * @param data xml stream
         * @param classe 类
         * @return jaxb生成xml的java 类对象
         */
        public static Object unmarshal(InputStream in, Class<?> classe) throws JAXBException, IOException {
            JAXBContext context = JAXBCache.instance().getJAXBContext(classe);
            byte[] data = IOUtils.toByteArray(in);
            Unmarshaller m = context.createUnmarshaller();
            ByteArrayInputStream inputStream = new ByteArrayInputStream(data);
            Object obj = m.unmarshal(inputStream);
            return obj;
        }
        public static void main(String[] args) throws JAXBException {
            Userinfo userinfo = new Userinfo();
            userinfo.setId(Long.valueOf(11));
            List<Overinfo> list = new ArrayList<Overinfo>();
            Overinfo e = new Overinfo();
            e.setHobby("陪女友");
            list.add(e);
            Overinfo e1 = new Overinfo();
            e1.setHobby("写代码");
            list.add(e1);
            userinfo.setOverinfos(list);
            byte[] b = JAXBUtil.marshal(userinfo);
            System.out.println(new String(b));
            userinfo = (Userinfo) JAXBUtil.unmarshal(b, Userinfo.class);
            System.out.println(userinfo.getOverinfos().get(0).getHobby());
        }
    }

    就不说明了,仔细看代码的,一会就明白了.不看的运行下也明白了.下面是上面main方法测试的输出结果:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <userinfo>
        <id>11</id>
        <overinfos>
            <overinfo>
                <hobby>陪女友</hobby>
            </overinfo>
            <overinfo>
                <hobby>写代码</hobby>
            </overinfo>
        </overinfos>
    </userinfo>

    陪女友

    下面是使用JAXBExportSchema 导出JAXB的 class的 结构

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
      <xs:element name="userinfo" type="userinfo"/>
      <xs:complexType name="userinfo">
        <xs:sequence>
          <xs:element name="id" type="xs:long" minOccurs="0"/>
          <xs:element name="name" type="xs:string" minOccurs="0"/>
          <xs:element name="address" type="xs:string" minOccurs="0"/>
          <xs:element name="job" type="xs:string" minOccurs="0"/>
          <xs:element name="overinfos" minOccurs="0">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="overinfo" type="overinfo" minOccurs="0" maxOccurs="unbounded"/>
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        </xs:sequence>
      </xs:complexType>
      <xs:complexType name="overinfo">
        <xs:sequence>
          <xs:element name="hobby" type="xs:string" minOccurs="0"/>
          <xs:element name="beginDate" type="xs:dateTime" minOccurs="0"/>
          <xs:element name="endDate" type="xs:dateTime" minOccurs="0"/>
        </xs:sequence>
      </xs:complexType>
    </xs:schema>
  • 相关阅读:
    安卓学习-activity-窗体调用和传参
    安卓学习-activity-PreferenceActivity
    安卓学习-activity-ExpandableListActivity
    安卓学习-activity-LauncherActivity
    安卓学习-界面-事件-AsyncTask
    安卓学习-界面-事件-handler
    安卓学习-界面-事件-Configuration
    安卓学习-界面-ui-菜单ActionBar
    安卓学习-界面-ui-普通菜单
    C++实现成绩管理模拟系统
  • 原文地址:https://www.cnblogs.com/cnsdhzzl/p/8390514.html
Copyright © 2011-2022 走看看