Spring和JAXB2.0结合使用

由于XML在分布式系统中应用如此广泛,而java又是开发网络和分布式系统可选的最佳运行环境之一,因此,java提供了很多的库,使编程人员能够轻松处理XML数据。在早期,java主要以JAXP定义的相关接口和类处理XML文档。JAXP中包括基于树结构的DOM和基于流方式的SAXStAX。随着面向对象技术的不断发展,像JAXP这样低层次的XML处理方式,无法满足日益增长的程序规模的需求,因此XOMXML文档和对象映射)被提出,Java通过对XOM的需求的研究(JSR222),提出了JAXB框架。JAXB框架主要是解决java对象与XML文档映射问题。

       Spring技术已经发展到3.0版本,在过去的几年里,Spring真的如其名字一样给计算机网络服务编程带来了春天。现在Spring技术已经得到了国内软件行业的认可,并且有继续扩展的趋势。Spring回避了EJB的缺陷,发扬了EJB的优点,已然成为JavaEE的一个经典框架。

       最近在研究Restful服务技术,而XMLRestful的一个主要信息载体,使用JAXB完成XMLJava对象的映射又是比较常用的策略(实际使用Castor等框架也可完成XOM)。在Restful中,我们先定义一个通信两端的通信协议(一般是一个schema文件,描述了通信两端交换的数据格式和内容),之后两端各自根据通信协议完成各自的实现,因此,通信两端可以是编程环境和运行环境异构的。例如:通信两端中,一端是java程序,另一端是c程序,而他们之间的通信使用RestfulHttp协议)并且信息载体是XMLjavac都可以处理XML文档,获取文档中需要的信息(XML信息的内容和格式由schema定义的),因此就完成了跨平台,跨执行环境的通信。在java端,JAXB可以通过Schema自动生成Java类对象,并且JAXB按照Schema的标准将java对象编组到XML文档中,也能从XML文档中解组出java对象,这样就大大提高了对通信信息的处理能力。

       对于java来说,使用Restful服务的简单方法就是使用SpringMVC,因为SpringMVC本身就是基于Restful的目的编写的(实际上,JavaEE6提供的JAX-RSjavaRestful的实现框架,但是,我们希望应用更多的Spring特性(依赖注入和控制反转)来简化我们的服务搭建,因此使用的是SpringMVC来完成Restful服务)。

       综上,我们看到了在Spring中使用JAXB的重要性,以及它在我们的Restful服务搭建环节上的地位,下面将简述如何在Spring中使用JAXB2.

 

1、编写schema文档

我们打算创建两个数据模型,一个是student.xsd,描述了关于student的定义,一个是teacher.xsd描述teacher的定义。定义两个xsd文件的目的是为了解释一个JAXBContent能包含多个根元素,并没有特殊意义。

Student.xsd

<?xml version="1.0" encoding="UTF-8"?>

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

    <xsd:element name="student">

       <xsd:complexType>

           <xsd:sequence>

              <xsd:element name="name" type="xsd:string"/>        

           </xsd:sequence>

           <xsd:attribute name="id" type="xsd:int"/>

       </xsd:complexType>

    </xsd:element>

</xsd:schema>

Teacher.xsd

<?xml version="1.0" encoding="UTF-8"?>

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

    <xs:element name="teacher">

       <xs:complexType>

           <xs:sequence>

              <xs:element name="name" type="xs:string"/>

           </xs:sequence>

       </xs:complexType>

    </xs:element>

</xs:schema>

2. 使用xjc编译生成java

       JAXB能够从schema转换出java的类,同时也能从java类转换出schema。根据我们前面的分析,schema实际是通信双方的标准,因此,先定义出schema,之后通过schema生成java类似乎更合理。因此我们采用xjcschema生成java类。

       使用命令行,转换出student类,输入如下信息:

I:\programs\eclipse\SpringJAXBTest\src>xjc -p cn.edu.upc.upcgrid.guan.springjaxb

.student   Student.xsd

xjc XML to Java Compiler)是java提供的工具,在java安装后就可以使用这个工具(注意要将java的环境变量配置正确),-p 后面的参数是生成类的包名和转换的schema文件的路径。

       同理使用命令行,将Teacherschema转换成teacher类。

I:\programs\eclipse\SpringJAXBTest\src>xjc -p com.upc.upcgrid.guan.springjaxb.st

udent Teacher.xsd

       现在,刷新我们的工程,会出现有xjc生成的类。(注意,ObjectFactory没有用处,因此可以直接删除,ObjectFactory在某些情况下有用,不过那是复杂的schema映射,比如choice元素等,如果希望了解更多,请参考我的其他关于JAXB的博客)。

Student.java类的内容大致如下:

package com.upc.upcgrid.guan.springjaxb.student;

 

import javax.xml.bind.annotation.XmlAccessType;

import javax.xml.bind.annotation.XmlAccessorType;

import javax.xml.bind.annotation.XmlAttribute;

import javax.xml.bind.annotation.XmlElement;

import javax.xml.bind.annotation.XmlRootElement;

 

@XmlAccessorType(XmlAccessType.FIELD)

@XmlRootElement(name="student")

public class Student {

 

    @XmlElement(required = true)

    protected String name;

    @XmlAttribute

    protected Integer id;

 

    public String getName() {

        return name;

    }

 

 

    public void setName(String value) {

        this.name = value;

    }

 

    public Integer getId() {

        return id;

    }

 

    public void setId(Integer value) {

        this.id = value;

    }

 

}

 

生成的Teacher.java类的大致内容如下:

package com.upc.upcgrid.guan.springjaxb.student;

 

import javax.xml.bind.annotation.XmlAccessType;

import javax.xml.bind.annotation.XmlAccessorType;

import javax.xml.bind.annotation.XmlElement;

import javax.xml.bind.annotation.XmlRootElement;

import javax.xml.bind.annotation.XmlType;

 

@XmlAccessorType(XmlAccessType.FIELD)

@XmlType(name = "", propOrder = {

    "name"

})

@XmlRootElement(name = "teacher")

public class Teacher {

 

    @XmlElement(required = true)

    protected String name;

 

    public String getName() {

        return name;

    }

 

    public void setName(String value) {

        this.name = value;

    }

 

}

可以看出,xjc生成的TeacherStudent类只不过是一些getset方法,并且添加了一些标记(在JAXB中,如果会使用这些标记,可以在自定义的类中使用这些标记,就不用定义schema)。

3. 配置Spring环境

这里为了简单起见,我们不使用XML方式配置Spring,而是采用Annotation的方式对Spring进行配置。

这里有两个类,SpringConfigure用来替代以前的spring-servlet.xml(就是spring的配置文档)。为了方便使用,我们又创建一个spring的注入类MarshalAndUnmarshalService,此类包含两个成员变量,分别为MarshallerUnmarshaller,我们可以使用这两个变量完成对Java对象的编组和对XML文档的解组。根据Spring的注入规则,我们看到Spring的配置文档中有一个Jaxb2Marshallerbean实例,这个实例有一个特点,它既是Marshaller类型,也是Unmarshaller类型,因此,在Spring依赖注入的过程中,MarshalAndUnmarshalService类中的marshallerunmarshaller实际注入的是同一个实例(即:Jaxb2Marshaller类的实例)。

      

Spring的配置文件SpringConfigure.java

package com.upc.upcgrid.guan.springjaxb;

 

import java.util.HashMap;

import java.util.Map;

 

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.oxm.jaxb.Jaxb2Marshaller;

 

import com.upc.upcgrid.guan.springjaxb.student.Student;

import com.upc.upcgrid.guan.springjaxb.student.Teacher;

 

 

@Configuration

public class SpringConfigure { 

    public @Bean Jaxb2Marshaller jaxb2Marshaller()//配置JAXB2Context

    {

       Jaxb2Marshaller marshaller = new Jaxb2Marshaller();//创建JAXB上下文环境

       Map<String,Object> properties = new HashMap<String, Object>();//创建映射,用于设置Marshaller属性

       properties.put(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);   //放置xml自动缩进属性

       marshaller.setClassesToBeBound(Student.class,Teacher.class);//映射的xml类放入JAXB环境中    

       marshaller.setMarshallerProperties(properties);//设置Marshaller属性

       return marshaller;

    }

   

    public @Bean MarshalAndUnmarshalService marshalAndUnmarshalService()

    {

       return new MarshalAndUnmarshalService();//创建和使用JAXB

    }

 

}

MarshalAndUnmarshalService.java

package com.upc.upcgrid.guan.springjaxb;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.oxm.Marshaller;

import org.springframework.oxm.Unmarshaller;

import org.springframework.stereotype.Component;

 

@Component

public class MarshalAndUnmarshalService{

    private Marshaller marshaller;//注入Marshaller

    private Unmarshaller unmarshaller;//注入Unmarshaller

   

    @Autowired

    public void setMarshaller(Marshaller marshaller) {

       this.marshaller = marshaller;

    }

    public Marshaller getMarshaller() {

       return marshaller;

    }

    @Autowired

    public void setUnmarshaller(Unmarshaller unmarshaller) {

       this.unmarshaller = unmarshaller;

    }

    public Unmarshaller getUnmarshaller() {

       return unmarshaller;

    }

   

}

 

4. 编写测试程序。

       现在我们的准备工作已经结束,剩下的就是测试,在MainTest.java中给出了如何使用Spring进行XOM映射。

       main函数中,先创建需要编组的对象,之后构建Spring环境,从Spring环境中获取到marshallerunmarshaller,最后完成编组和解组。

package com.upc.upcgrid.guan.springjaxb;

 

import java.io.File;

import java.io.IOException;

 

import javax.xml.transform.stream.StreamResult;

import javax.xml.transform.stream.StreamSource;

 

import org.springframework.context.ApplicationContext;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import org.springframework.oxm.XmlMappingException;

 

import com.upc.upcgrid.guan.springjaxb.student.Student;

import com.upc.upcgrid.guan.springjaxb.student.Teacher;

 

 

public class MainTest {

    public static void main(String[] args) throws XmlMappingException, IOException {

       //创建两个文件,分别输出不同的对象

       File file = new File("student.xml");

       File tFile = new File("teacher.xml");

       //创建学生

       Student student = new Student();

       student.setId(21231);

       student.setName("mary");

       //创建teacher

       Teacher teacher = new Teacher();

       teacher.setName("Lucy");

       //创建spring上下文(此时spring开始分析并创建单例类的对象)

       ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfigure.class);

       //获取到jaxb使用的工具

       MarshalAndUnmarshalService maus = ac.getBean(MarshalAndUnmarshalService.class);

       //将学生和教师数据编组到文件

       maus.getMarshaller().marshal(student, new StreamResult(file));

       maus.getMarshaller().marshal(teacher, new StreamResult(tFile));

       //将学生和教师信息解组到对象

       Student s = (Student) maus.getUnmarshaller().unmarshal(new StreamSource(file));

       Teacher t = (Teacher) maus.getUnmarshaller().unmarshal(newStreamSource(tFile));

       //输出学生和教师中的内容

       System.out.println(s.getName());

       System.out.println(t.getName());

    }

}

标准输出:

2011-6-23 20:22:54 org.springframework.context.support.AbstractApplicationContext prepareRefresh

信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@1113708: startup date [Thu Jun 23 20:22:54 CST 2011]; root of context hierarchy

2011-6-23 20:22:54 org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons

信息: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@1f33675: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,springConfigure,jaxb2Marshaller,marshalAndUnmarshalService]; root of factory hierarchy

2011-6-23 20:22:54 org.springframework.oxm.jaxb.Jaxb2Marshaller createJaxbContextFromClasses

信息: Creating JAXBContext with classes to be bound [class com.upc.upcgrid.guan.springjaxb.student.Student,class com.upc.upcgrid.guan.springjaxb.student.Teacher]

mary

Lucy

 

生成的XML文档:

Student.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<student id="21231">

    <name>mary</name>

</student>

Teacher.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

<teacher>

    <name>Lucy</name>

</teacher>

 

程序结构:

Spring和JAXB2.0结合使用

参考:

Spring官方文档

JAXB官方文档:http://jaxb.java.net/tutorial/index.html

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值