文档章节

使用JAXB2.0实现OXM

大侠柳云枫
 大侠柳云枫
发布于 2014/04/18 10:23
字数 3905
阅读 202
收藏 0

摘    要

Java Architecture for XML Binding (JAXB) 是一项可以根据XML 模式产生Java类的Java技术。该过程中,JAXB也提供了将XML实例文档反编组到Java内容树的方法,并能将Java内容树编组回XML实例文档。从另一方面来讲,JAXB提供了快速而简便的方法将XML模式绑定到Java表示,从而使得Java开发者在Java应用程序中能方便地结合XML数据和处理函数。

这意味着你不需要处理甚至不需要知道XML编程技巧就能在Java应用程序中利用平台核心XML数据的灵活性。而且,可以充分利用XML的优势而不用依赖于复杂的XML处理模型如SAX或DOM。JAXB 隐藏了细节并且取消了SAX和DOM中没用的关系——生成的JAXB类仅描述原始模型中定义的关系。其结果是结合了高度可移植Java代码的高度可移植的XML数据,其中这些代码可用来创建灵活、轻便的应用程序和Web服务。

一、OXM

OXMObject XML Mapping的缩写,它是一个O/M-mapper,将java对象映射成XML数据,或者将XML数据映射成java对象。我们把对象与关系数据库之间的映射称为ORM, 所以也把对象与XML之间的映射称为OXM

二、JAXB2.0

JAXBJava Architecture for XML Binding)是一种特殊的序列化/反序列化工具。它可以使XML数据以Java Objects的形式直接应用于Java程序之中,使Java ObjectsXML数据之间的转换成为可能。在JAXB中将Java ObjectsXML数据的转换称为marshalXML数据到Java Objects的转换称为unmarshal。原来JAXBJava EE的一部分,在JDK6中,SUN将其放到了Java SE中,这也是SUN的一贯做法。JDK6中自带的这个JAXB版本是2.0, 比起1.0(JSR 31)来,JAXB2(JSR 222)JDK5的新特性Annotation来标识要作绑定的类和属性等,这就极大简化了开发的工作量。实际上,在Java EE 5.0中,EJBWeb Services也通过Annotation来简化开发工作。另外,JAXB2在底层是用StAX(JSR 173)来处理XML文档。

JAXB数据绑定过程的常用步骤是:

 1 JAXB实现中的核心组件

组件

描述

XML Schema

XML模式使用XML语法描述XML文档中元素、属性和实体之间的关系。XML模式的目标是定义一个XML文档类,该类必须坚持特定的结构规则和数据约束。例如,你可能希望给面向章的书、在线采购系统或个人数据库定义不同的模式。在JAXB上下文中,将包含数据的受到XML模式约束的XML文档叫做文档实例,并且将文档实例中的结构和数据叫做内容树

Binding
Declarations

默认情况下,JAXB绑定编译器根据JAXB规范第5节“将XML Schema绑定到Java表示”中定义的规则将Java类和包绑定到原始XML模式。多数情况下,利用默认的规则已经能够从大量的模式中产生一组强壮的模式派生类。但是,有的时候,默认的绑定规则就不够用了。JAXB支持通过绑定声明自定义或覆盖默认的绑定规则。这些绑定声明或者是内部源模式的注释或者是传递给JAXB绑定编译器的外部绑定自定义文件中的语句。注意,自定义的JAXB绑定声明也允许摆脱XML模式中特定于XML的束缚,来自定义生成的JAXB类,以包含特定于Java的改进,如类和包名映射

Binding
Compiler

JAXB绑定编译器是JAXB处理模型的核心。它的功能是将源XML模式转换或绑定到Java编程语言中的一组JAXB内容类。基本上,可以通过将一个XML模式 (可以选择使用自定义绑定声明)用作输入来运行JAXB绑定编译器。绑定编译器产生Java类,这些Java类映射到了源XML 模式中的约束条件

Binding
Framework
Implementation

JAXB绑定框架实现是运行时API,它提供了反编组、编组和验证Java应用程序中的XML内容的接口。绑定框架包括javax.xml.bind 包中的接口

Schema-Derived
Classes

这些是JAXB编译器产生的模式派生类。根据输入的模式将采用不同的类

Java 
Application

JAXB上下文中,Java应用程序是客户端应用程序,它使用JAXB绑定框架来反编组XML数据,验证并修改Java内容对象,并将Java内容编组成XML数据。特别是,JAXB绑定框架包装在一个能提供UI功能、XML转换功能、数据处理或其他所需要的功能的大型Java应用程序中

XML Input
Documents

这是反编组出来用作JAXB绑定框架输入的XML内容——即XML实例文档,从这里将产生内容树形式的Java表示。实际上, 术语“文档”不再是传统意义上的文档了,因为XML实例文档不一定要是形式完整的、自立的文档文件;相反它具有流的形式,这些流可以是应用程序之间传递的数据、数据库字段集合、XML信息集合,其中信息块包含了描述它们在模式结构中的位置的足够信息。

 

JAXB中,反编组过程支持根据源模式定义的约束验证XML输入文档。然而该验证过程是可选的,在某些情况下你可能通过其他途径知道输入文档是有效的,出于对性能的考虑你可能选择在反编组过程中跳过验证。但是,无论在哪种情况下,反编组之前(通过第三方应用程序)或之后验证都很重要,这是因为它确保了关于源模式编组过程中产生的XML文档也是有效的。在本章的后面部分将详细介绍验证

XML Output
Documents

这是编组到XML文档的XML内容。在JAXB中,编组包括解析XML内容对象树并写出一个XML文档,该文档是原始XML文档的精确表示并且相对于原始模式来说是有效的。JAXB能够将XML数据编组成XML 文档、SAX内容处理程序和DOM节点。

1.生成类。将XML模式放入JAXB绑定编译器,以产生基于该模式的JAXB类。
2.编译类。 必须编译所有生成的类、源文件和应用程序代码。
3.反编组。JAXB绑定框架反编组根据原始模式中的约束编写的XML文档。注意JAXB也支持反编组来自除了文件/文档之外XML数据,如DOM节点、字符串缓冲、SAX Source等等。
4.生成内容树。 反编组过程产生从生成的JAXB类实例化而来的数据对象内容树,该内容树代表了源XML文档的结构和内容。
5.验证(可选)。 反编组过程中,可以在生成内容树之前验证源XML文档。注意,如果在第6步中修改内容树,下面,你也能使用JAXB验证操作在将内容编组到XML文档之前验证变化。
6.处理内容。客户端应用程序通过绑定编译器产生的接口方法可以修改Java内容树表示的XML数据。
7.编组。将处理过的内容树编组到一个或多个XML输出文档中。在编组之前要验证内容。


  优点:JAXB2.0支持使用Annotation在java代码中说明各种属性的XML风格,相当的方便。
  JAXB中主要的注解(javax.xml.bind.annotation):
  @XmlRootElement   将一个Java类映射为一段XML的根节点
  参数:name            定义这个根节点的名称
  Namespace 定义这个根节点命名空间
   
  @XmlAccessorType  定义映射这个类中的何种类型需要映射到XML。可接收四个参数,分别是:
  XmlAccessType.FIELD:映射这个类中的所有字段到XML
  XmlAccessType.PROPERTY:映射这个类中的属性(get/set方法)到XML
  XmlAccessType.PUBLIC_MEMBER:将这个类中的所有public的field或property同时映射到XML(默认)
  XmlAccessType.NONE:不映射
   
  @XmlElement  指定一个字段或get/set方法映射到XML的节点。如,当一个类的XmlAccessorType 被标注为PROPERTY时,在某一个没有get/set方法的字段上标注此注解,即可将该字段映射到XML。
  参数:defaultValue  指定节点默认值
        name             指定节点名称
        Namespace 指定节点命名空间
        required           是否必须(默认为false)
        nillable            该字段是否包含 nillable="true" 属性(默认为false)
        type               定义该字段或属性的关联类型
   
  @XmlAttribute  指定一个字段或get/set方法映射到XML的属性。
  参数:name             指定属性名称
        namespace    指定属性命名空间
        required         是否必须(默认为false)
   
  @XmlTransient  定义某一字段或属性不需要被映射为XML。如,当一个类的XmlAccessorType 被标注为PROPERTY时,在某一get/set方法的字段上标注此注解,那么该属性则不会被映射。
   
  @XmlType  定义映射的一些相关规则
  参数:propOrder        指定映射XML时的节点顺序
        factoryClass     指定UnMarshal时生成映射类实例所需的工厂类,默认为这个类本身
        factoryMethod  指定工厂类的工厂方法
        name               定义XML Schema中type的名称
        namespace      指定Schema中的命名空间 
  
  @XmlElementWrapper  为数组元素或集合元素定义一个父节点。如,类中有一元素为List items,若不加此注解,该元素将被映射为
      <items>...</items>
      <items>...</items>
  这种形式,此注解可将这个元素进行包装,如:
  @XmlElementWrapper(name="items")    @XmlElement(name="item")    public List items;
  将会生成这样的XML样式:
      <items>
          <item>...</item>
          <item>...</item>
      </items> 
  
  @XmlJavaTypeAdapter  自定义某一字段或属性映射到XML的适配器。如,类中包含一个接口,我们可以定义一个适配器(继承自javax.xml.bind.annotation.adapters.XmlAdapter类),指定这个接口如何映射到XML。 
  
  @XmlSchema 配置整个包的namespace,这个注解需放在package-info.java文件中。

三、Object to XML应用实例

①Address.java

@XmlRootElement(name = "address")
public class Address {

    /** code */
    private int code;
 
    /** company */
    private String name;
  
    /**
     * @return 获取 code属性值
     */
    public int getCode() {
        return code;
    }

    /**
     * @param code 设置 code 属性值为参数值 code
     */
    public void setCode(int code) {
        this.code = code;
    }
    
    /**
     * @return 获取 name属性值
     */
    public String getName() {
        return name;
    }
    
    /**
     * @param name 设置 name 属性值为参数值 name
     */
    public void setName(String name) {
        this.name = name;
    }    
}

②OXMapper.java

public class OXMapper {
    
    /** 日志对象 */
    private static final Logger LOG = LoggerFactory.getLogger(OXMapper.class);
    
    /** Marshaller */
    private Marshaller marshaller;
    
    /** Unmarshaller */
    private Unmarshaller unmarshaller;
    
    /**
     * @return 获取 marshaller属性值
     */
    public Marshaller getMarshaller() {
        return marshaller;
    }
    
    /**
     * @param marshaller 设置 marshaller 属性值为参数值 marshaller
     */
    public void setMarshaller(Marshaller marshaller) {
        this.marshaller = marshaller;
    }
    
    /**
     * @return 获取 unmarshaller属性值
     */
    public Unmarshaller getUnmarshaller() {
        return unmarshaller;
    }
    
    /**
     * @param unmarshaller 设置 unmarshaller 属性值为参数值 unmarshaller
     */
    public void setUnmarshaller(Unmarshaller unmarshaller) {
        this.unmarshaller = unmarshaller;
    }
    
    /**
     * 将对象转换输出为xml文件
     * 
     * @param object object 对象
     * @param filename filename 文件名
     * @throws IOException IOException IO异常
     */
    public void writeObjectToXml(Object object, String filename) throws IOException {
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(filename);
  marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
            marshaller.marshal(object, new StreamResult(fos));
        } catch (JAXBException e) {
            LOG.error("Xml-Serialization failed due to an XmlMappingException.", e);
        } catch (IOException e) {
            LOG.error("Xml-Serialization failed due to an IOException.", e);
        } finally {
            if (fos != null) {
                fos.close();
            }
        }
    }
    
    /**
     * 将xml文件转换成java对象
     * 
     * @param filename filename 文件名称
     * @return Object 转换后的java对象
     * @throws IOException IOException IO异常
     * @throws JAXBException JAXBException JAXB异常
     */
    public Object readObjectFromXml(String filename) throws IOException, JAXBException {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(filename);
            return unmarshaller.unmarshal(new StreamSource(fis));
        } catch (IOException e) {
            LOG.error("Xml-Deserialization failed due to an IOException.", e);
        } finally {
            if (fis != null) {
                fis.close();
            }
        }
        return null;
    }
    
    /**
     * 测试用例
     * 
     * @param args 传入参数
     * @throws IOException IOException
     * @throws JAXBException JAXBException
     */
    public static void main(String[] args) throws IOException, JAXBException {
        Address address = new Address();
        address.setCode(58888);
        address.setName("深圳市福田区莲花路2075号香丽大厦首层");
        
        JAXBContext objJaxbContext = JAXBContext.newInstance(Address.class);
        Marshaller objMarshaller = objJaxbContext.createMarshaller();
        
        Unmarshaller objUnmarshaller = objJaxbContext.createUnmarshaller();
        
        OXMapper oxMapper = new OXMapper();
        oxMapper.setMarshaller(objMarshaller);
        oxMapper.writeObjectToXml(address, "address.xml");
        
        oxMapper.setUnmarshaller(objUnmarshaller);
        Address objAddress = (Address) oxMapper.readObjectFromXml("address.xml");
        System.out.println(ReflectionToStringBuilder.toString(objAddress, ToStringStyle.MULTI_LINE_STYLE));
    }
}



四、XML TO Java 应用实例

①XML to XSD工具

1.XMLSPy

采用XMLSPy工具生成test.xml对应的xsd。
  (1):点击“DTD/模式”菜单
  (2):选择“W3C模式”,点击确定

2.Trang

    Trang的执行: java -jar trang.jar -I rng|rnc|dtd|xml -O rng|rnc|dtd|xsd [其它参数] 输入文件名 输出文件名 -I : 输入文件的格式 -O : 输出文件的格式
  必须是大写,小写不识别
  
 java -jar trang.jar Address.xml Address.xsd。

②XJC(XML to Java Compiler)工具

  JAXB能够从schema转换出java的类,同时也能从java类转换出schema。schema实际是通信双方的标准,因此,先定义出schema,之后通过schema生成java类似乎更合理。因此我们采用java自带的工具xjc从schema生成java类。
  命令行程序xjc用于编译DTD或Schema生成与XML数据结构对应的JavaBeans类。操作方法如下:
  xjc [-xmlschema|-dtd] [–d 保存java文件的目录] [–p java文件所在的包] <编译文件>
  -xmlschema  指定编译文件的格式为Schema格式,此参数是默认值,可以不用提供。如果不提供此参数,编译文件必须是Schema文件。 -dtd  指定编译文件的格式为DTD格式,如果编译文件是DTD文件则必须提供此参数。 -d  指定了保存java文件的目录 -p  指定了生成的java文件所在的包
  
  使用命令行,转换出Address类,输入如下信息:
  xjc -p com.comtop Address.xsd
  xjc XML to Java Compiler)是java提供的工具,在java安装后就可以使用这个工具(注意要将java的环境变量配置正确),-p 后面的参数是生成类的包名和转换的schema文件的路径。
  会在com.comtop包目录下生成两个类:Address.java和ObjectFactory.java

测试程序:

public class Test {
    /**
   *  测试程序
     * @param args
     * @throws Exception 
     */
    public static void main(String[] args) throws Exception {
          JAXBContext context = JAXBContext.newInstance(ObjectFactory.class);
          Marshaller objMarshaller = context.createMarshaller();
          ObjectFactory  objectFactory=new ObjectFactory();
          com.comtop.Address address=objectFactory.createAddress();
          address.setName("广东省深圳市福田区");
          address.setCode(588888);
          FileOutputStream fos= new FileOutputStream("Address2.xml");
          objMarshaller.marshal(address,new StreamResult(fos));
    } 
}



五、Spring 扩展

  Spring-OXM作为Spring-WS的一个子项目在通用的OXM解决方案(如JAXB和Castor XML)之上提供了一层抽象层。
  Spring OXM核心元素是Marshaller和Unmarshaller接口。实现Marshaller接口可以实现从Java对象到XML消息的转换;实现Unmarshaller接口可实现从XML消息到java对象的转换。
  不需要自己实现Marshaller和Unmarshaller,Spring-OXM提供了一些具体的实现,如CastorMarshaller和Jaxb2Marshaller等。它们同时实现了Marshaller和UnMarshaller接口,从而可以提供一应俱全的功能。

六、参考资料

1.JAXB

2.使用JAXBXML Schema绑定到Java

3.Trang

4.Java Web 服务: Axis2 中的 JAXB 和 JAX-WS

本文转载自:http://my.oschina.net/zzx0421/blog/98186

上一篇: JAXB2.0之日常使用
下一篇: Java学习路线
大侠柳云枫

大侠柳云枫

粉丝 10
博文 58
码字总数 2831
作品 0
长沙
程序员
私信 提问
Jfinal中使用自带jetty,在jdk1.6中对于使用jaxb2.0以上版本导致jar包冲突,有什么解决方案么?

@JFinal 你好,想跟你请教个问题: Jfinal中使用自带jetty,在jdk1.6中对于使用jaxb2.0以上版本导致jaxb-api.jar包冲突,有什么解决方案么?

Retire
2015/11/12
235
2
企业ORM平台--EclipseLink/TopLink

Oracle 最近宣布把企业级的ORM平台TopLink代码捐献给Eclipse社区,发起并领导名为EclipseLink的Eclipse持久平台项目。 Eclipse持久平台由多个组件构成,主要有EclipseLink-ORM,EclipseLink...

匿名
2008/10/05
14K
0
关于Spring Data redis几种对象序列化的比较

问题 最近在整一个spring data redis,网上有一本《Spring Data》的电子书(我一个朋友正在翻译,应该今年会有中文版出来,人邮的),下载来看了一下,其中第8章讲到了Spring data对redis的支...

stamen
2015/08/21
411
0
二、idea导入spring源码

在 fork 官方源码 到自己的仓库后(fork 的好处是方便自己试验和注释), 将其 git clone 下来, 因平时工作用的是 idea 就想用 idea 作为工具。 clone 下来后可以看到根目录下有2个指引文件...

holysu
2018/07/11
0
0
Spring框架基础知识

本人博客文章网址:https://www.peretang.com/basic-knowledge-of-spring-framework/ Spring框架简介 Spring , 一个开源的框架 , 由Rod Johnson创建. Spring是为了解决企业应用开发的复杂性而...

PereTang
2017/05/03
0
0

没有更多内容

加载失败,请刷新页面

加载更多

spring cloud

一、从面试题入手 1.1、什么事微服务 1.2、微服务之间如何独立通讯的 1.3、springCloud和Dubbo有哪些区别 1.通信机制:DUbbo基于RPC远程过程调用;微服务cloud基于http restFUL API 1.4、spr...

榴莲黑芝麻糊
56分钟前
2
0
Executor线程池原理与源码解读

线程池为线程生命周期的开销和资源不足问题提供了解决方 案。通过对多个任务重用线程,线程创建的开销被分摊到了多个任务上。 线程实现方式 Thread、Runnable、Callable //实现Runnable接口的...

小强的进阶之路
昨天
6
0
maven 环境隔离

解决问题 即 在 resource 文件夹下面 ,新增对应的资源配置文件夹,对应 开发,测试,生产的不同的配置内容 <resources> <resource> <directory>src/main/resources.${deplo......

之渊
昨天
8
0
详解箭头函数和普通函数的区别以及箭头函数的注意事项、不适用场景

箭头函数是ES6的API,相信很多人都知道,因为其语法上相对于普通函数更简洁,深受大家的喜爱。就是这种我们日常开发中一直在使用的API,大部分同学却对它的了解程度还是不够深... 普通函数和...

OBKoro1
昨天
7
0
轻量级 HTTP(s) 代理 TinyProxy

CentOS 下安装 TinyProxy yum install -y tinyproxy 启动、停止、重启 # 启动service tinyproxy start# 停止service tinyproxy stop# 重启service tinyproxy restart 相关配置 默认...

Anoyi
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部