《Spring官方文档》17.利用O/X映射器编组XML

原文链接 译者:kdmhh

17. 利用O/X映射器编组XML

17.1 引言

这一章,我们将介绍Spring对对象/XML映射器的支持。对象/XML映射器或者简称O/X映射器,是一种在XML文档和对象之间互相转换的行为。这种转换过程也叫做XML编组或者XML序列化。本章将交替使用这两种术语。

在O/X映射器中,编组是指把对象序列化为XML的过程。同样,解组是指XML反序列化为对象,XML可以是DOM文档、输入输出流或者SAX处理程序。

使用Spring处理O/X映射器的好处是:

17.1.1 简化的配置

Spring的bean工厂使得不需要构建JAXB、JiBX等第三方工具,就可以轻松配置编组器。编组器在应用程序上下文中可以配置为任意的bean。另外,基于XML的配置可应用于不同的编组器,并让配置更加简单化。

17.1.2 统一的接口

Spring的O/X映射器通过两个全局接口来实现:Marshaller 和 Unmarshaller。这些接口使你可以相对轻松切换O/X映射框架,你只需改动少量或者无需改动实现编组器的类。这种方式的另外优点是在同一个应用程序中以一种非侵入式的方式,将多种技术通过混合的方式来实现编组(比如,一些编组通过JAXB实现,而另外的通过Castor)。

17.1.3 统一的异常层次结构

Spring提供了基于底层O/X映射工具自身的异常层次结构,以XmlMappingException作为基础异常。这样原始异常被包装到Spring运行时异常中,保证了没有信息丢失。

17.2 编组和解组

正如引言中所述,编组是将对象序列化为XML,解组是将XML流反序列化为对象。这一章节,我们讲描述达到此目标的两个Spring接口。

17.2.1 编组

Spring通过org.springframework.oxm.Marshaller接口抽象出所有编组操作,下面列出了主体方法。

public interface Marshaller {

/**
* Marshal the object graph with the given root into the provided Result.
*/
void marshal(Object graph, Result result) throws XmlMappingException, IOException;
}

Marshaller接口只有一个主体方法,这个方法将给定的对象编组为javax.xml.transform.Result。Result是一个标记接口,它表示一个XML的输出抽象:具体的实现封装了各种XML的表示,如下表所示:

Result实现类 封装的XML表示
DOMResult org.w3c.dom.Node
SAXResult org.xml.sax.ContentHandler
StreamResult java.io.File, java.io.OutputStream, 或者 java.io.Writer

尽管marshal()方法接收一个普通对象作为它的第一个参数,但大多数编组器实现不能处理任意对象。相反地,对象类必须映射到文件中,标记为注释,并且注册为编组器,或者有一个公共基类。请参阅本章节的其他内容,来决定你的O/X技术选择。

17.2.2 解组

与Marshaller接口类似,org.springframework.oxm.Unmarshaller 接口如下:

public interface Unmarshaller {

/**
* Unmarshal the given provided Source into an object graph.
*/
Object unmarshal(Source source) throws XmlMappingException, IOException;
}

这接口也有一个方法,读取给定的javax.xml.transform.Source 类(XML输入抽象),返回对象。与Result类一样,Source是一个有三个具体实现的标记接口,每一个都封装了不同的XML表示,如下表所示。

Source实现类 封装的XML表示
DOMSource org.w3c.dom.Node
SAXSource org.xml.sax.InputSource 和 org.xml.sax.XMLReader
StreamSource java.io.File,java.io.InputStream 或者java.io.Reader

尽管有两个单独的编组接口(Marshaller 和 Unmarshaller),但是所有在Spring-WS中的实现都在同一个类中。这意味着你也可以在applicationContext.xml引用同一个编组器类,并将其同时作为编组器和接编器。

17.2.3 XmlMappingException

Spring提供了基于底层O/X映射工具自身的异常层次结构,以XmlMappingException作为基础异常。这样原始异常被包装到Spring运行时异常中,保证了没有信息丢失。

另外,尽管基于底层O/X的映射工具并未提供,但是,MarshallingFailureException 和 UnmarshallingFailureException提供了编组和解组之间的差异操作。

O/X映射异常层次结构如下所示:

 

17.3 使用编组器和解组器

Spring的OXM可以被使用在各种场景下,在下面的实例中,我们将使用它把Spring管理的应用设置编组为XML文件,我们使用一个简单的JavaBean来表示这种设置。

public class Settings {

private boolean fooEnabled;

public boolean isFooEnabled() {
return fooEnabled;
}

public void setFooEnabled(boolean fooEnabled) {
this.fooEnabled = fooEnabled;
}
}

Application类使用这个类存储配置信息,除了main方法,这个类有两个方法:saveSettings()方法用来保存配置bean到settings.xml文件,loadSettings()方法用来再次加载这些配置。main()方法构造了Spring应用上下文,并调用了这两个方法。

import java.io.FileInputStream;
import java.io.FileOutputStream;
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.support.ClassPathXmlApplicationContext;
import org.springframework.oxm.Marshaller;
import org.springframework.oxm.Unmarshaller;

public class Application {

private static final String FILE_NAME = “settings.xml”;
private Settings settings = new Settings();
private Marshaller marshaller;
private Unmarshaller unmarshaller;

public void setMarshaller(Marshaller marshaller) {
this.marshaller = marshaller;
}

public void setUnmarshaller(Unmarshaller unmarshaller) {
this.unmarshaller = unmarshaller;
}

public void saveSettings() throws IOException {
FileOutputStream os = null;
try {
os = new FileOutputStream(FILE_NAME);
this.marshaller.marshal(settings, new StreamResult(os));
} finally {
if (os != null) {
os.close();
}
}
}

public void loadSettings() throws IOException {
FileInputStream is = null;
try {
is = new FileInputStream(FILE_NAME);
this.settings = (Settings) this.unmarshaller.unmarshal(new StreamSource(is));
} finally {
if (is != null) {
is.close();
}
}
}

public static void main(String[] args) throws IOException {
ApplicationContext appContext =
new ClassPathXmlApplicationContext(“applicationContext.xml”);
Application application = (Application) appContext.getBean(“application”);
application.saveSettings();
application.loadSettings();
}
}

Application 同时需要设置marshaller 和 unmarshaller两个属性,我们通过下面的applicationContext.xml来实现。

<beans>
    <bean id="application" class="Application">
        <property name="marshaller" ref="castorMarshaller" />
        <property name="unmarshaller" ref="castorMarshaller" />
    </bean>
    <bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller"/>
</beans>

这个应用上下文使用了Castor,但是你可以使用任一在本章节中介绍的其他编组器接口。注意的是,Castor在默认情况下不需要任何进一步的配置,所以bean的定义相当简单。同样需要注意的是,CastorMarshaller同时实现了Marshaller 和 Unmarshaller,所以我们可以同时在marshaller 和 unmarshaller 两个属性中引用castorMarshaller bean。

这个样例应用生成以下settings.xml文件。

<?xml version="1.0" encoding="UTF-8"?>
<settings foo-enabled="false"/>

17.4 XML配置

可以使用OXM命名空间标记更加简洁地配置编组器。要使这些标签可用,必须首先在XML配置文件头部引入适当的模板,注意下面“OXM”相关的配置:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:oxm="http://www.springframework.org/schema/oxm" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm.xsd">

目前,可以使用以下标签:

每个标记将在各自的编组器部分中进行详述。这里据一个示例,下面是JAXB2编组器的配置方式:

<oxm:jaxb2-marshaller id="marshaller" contextPath="org.springframework.ws.samples.airline.schema"/>

17.5 JAXB

JAXB绑定编辑器将一个W3C XML模板转换为一个或多个java类,jaxb.properties配置文件或者其他资源文件。JAXB还提供了从注解类生成模板的方法。

17.5.1 Jaxb2Marshaller

Jaxb2Marshaller类同时实现了Spring的Marshaller和Unmarshaller接口,它需要上下文路径,你可以通过contextPath属性设置。上下文路径是一个以冒号分割的java包名列表,这些包包含从模板派生的类。它还提供了一个classestobe绑定属性,允许你设置为类的数组,这些类要被编组器所支持。通过向bean指定一个或多个模式资源来进行模式验证,如下所示:

<beans>
    <bean id="jaxb2Marshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
        <property name="classesToBeBound">
            <list>
                <value>org.springframework.oxm.jaxb.Flight</value>
                <value>org.springframework.oxm.jaxb.Flights</value>
            </list>
        </property>
        <property name="schema" value="classpath:org/springframework/oxm/schema.xsd"/>
    </bean>

</beans>

基于XML的配置

jaxb2-marshaller标签配置为org.springframework.oxm.jaxb.Jaxb2Marshaller,如下示例:

<oxm:jaxb2-marshaller id="marshaller" contextPath="org.springframework.ws.samples.airline.schema"/>

编组器绑定的类列表也可以通过class-to-be-bound子标签提供:

<oxm:jaxb2-marshaller id="marshaller">
    <oxm:class-to-be-bound name="org.springframework.ws.samples.airline.schema.Airport"/>
    <oxm:class-to-be-bound name="org.springframework.ws.samples.airline.schema.Flight"/>
    ...
</oxm:jaxb2-marshaller>

可用的属性有:

属性 描述 是否必需
id 编组器的id
contextPath JAXB上下文路径

17.6 Castor

Castor XML映射是一个开源的XML绑定框架,它允许在java对象包含的数据和XML文档之间互相转换。默认情况下,它不需要任何进一步的配置,但是可以通过映射文件对Castor的行为进行更多的控制。

关于Castor更多的信息,请参阅Castor站点。Spring集成Castor的类放在org.springframework.oxm.castor包下。

17.6.1 CastorMarshaller

与JAXB类似,CastorMarshaller也同时实现了Marshaller 和Unmarshaller 接口,它可以通过如下方式配置:

<beans>
    <bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller" />
    ...
</beans>

17.6.2 映射器

尽管可以依赖Castor的默认编组行为,但是可能需要对它进行更多的控制,可以使用Castor映射文件来进行控制,更多的信息,请参考Castor XML映射

映射器可以通过mappingLocation属性来设置,可以通过如下的classpath资源来表示:

<beans>
    <bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller" >
        <property name="mappingLocation" value="classpath:mapping.xml" />
    </bean>
</beans>

XML配置

通过castor-marshaller标签配置org.springframework.oxm.castor.CastorMarshaller,下面是示例:

<oxm:castor-marshaller id="marshaller" mapping-location="classpath:org/springframework/oxm/castor/mapping.xml"/>

编组器实例可以通过两种方式配置,一种是指定映射文件的地址(通过mapping-location属性),另一种是通过识别java POJOs(通过target-class或target-package属性)对应的XML描述类。第二种方法通常与XML模板生成的XML代码结合使用。

可用的属性如下:

属性 描述 是否必需
id 编组器的id
encoding XML解码的编码格式
target-class Java类名,一个可以使用XML类描述符的POJO(通过代码生成)
target-package java包名,标识包含POJO及其相应的Castor XML描述类的包
mapping-location Castor XML映射文件的路径

17.7 JiBX

JiBX框架提供了与Hibernate提供的ORM类似的解决方案:定义了Java对象和XML相互转换的规则。在准备好绑定和编译类之后,JiBX绑定编译器会增强类文件,并添加代码来处理类和XML相互转化的实例。

更多的信息,请参考JiBX web site,Spring集成JiBX的类放在org.springframework.oxm.jibx包下。

17.7.1 JibxMarshaller

JibxMarshaller类同时实现了Marshaller和Unmarshaller接口,使用时,需要注入类名,可以通过targetClass或者bindingName属性进行设置。下面的列子中,我们绑定类Flights:

<beans>
    <bean id="jibxFlightsMarshaller" class="org.springframework.oxm.jibx.JibxMarshaller">
        <property name="targetClass">org.springframework.oxm.jibx.Flights</property>
    </bean>
    ...
</beans>

JibxMarshaller配置为了单个类,如果想配置多个类,需要通过不同的targetClass属性,配置多个JibxMarshaller。

XML配置

jibx-marshaller标签配置了一个org.springframework.oxm.jibx.JibxMarshaller类,示例如下:

<oxm:jibx-marshaller id="marshaller" target-class="org.springframework.ws.samples.airline.schema.Flight"/>

可用的属性如下:

属性 描述 是否必需
id 编组器的id
target-class 编组器的目标类
bindingName 编组器使用的绑定名称

17.8 XStream

XStream是一个简单类库,用于在对象和XML之间转换。它不需要任何映射器就可以生成XML。

更多信息,请参阅XStream web,Spring集成XStream的类在org.springframework.oxm.xstream包下。

17.8.1 XStreamMarshaller

XStreamMarshaller不需要任何配置,可以直接在上下文中配置。可以通过设置analiasMap属性进一步设置XML,它由类的字符串别名组成。

<beans>
    <bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
        <property name="aliases">
            <props>
                <prop key="Flight">org.springframework.oxm.xstream.Flight</prop>
            </props>
        </property>
    </bean>
    ...
</beans>

默认情况下,XStream允许任意类被解组,这可能导致安全漏洞。因此,不建议使用XStreamMarshaller从外部资源(即Web资源)中对XML进行解组,因为这会导致安全漏洞。如果确实使用了XStreamMarshaller从外部资源解组,那需要在XStreamMarshaller上设置supportedClasses属性,如下:

<bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
    <property name="supportedClasses" value="org.springframework.oxm.xstream.Flight"/>
    ...
</bean>

这能保证只有注册类才可以进行解组。另外,还可以注册自定义的转换器,确保只有支持的类可以被解组。除了支持应该支持的转换器外,你可能想要添加CatchAllConverter作为列表最后一个转换器,默认的XStream转换器具有较低的优先级和安全漏洞,因此不会被调用。

注意,XStream是一个XML序列化库,而不是一个数据绑定库。因此,它仅支持有限的名称空间,因此,它不适合在Web服务中使用。

 

原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: 《Spring官方文档》17.利用O/X映射器编组XML

  • Trackback 关闭
  • 评论 (0)
  1. 暂无评论

return top