On this page
21. 使用 O/XMap 器编组 XML
21.1 Introduction
在本章中,我们将描述 Spring 的对象/ XMLMap 支持。对象/ XMLMap(简称 O/XMap)是将 XML 文档与对象进行相互转换的操作。此转换过程也称为 XML 编组或 XML 序列化。本章可以互换使用这些术语。
在 O/XMap 领域中,* marshaller *负责将对象(图形)序列化为 XML。 * unmarshaller *以类似的方式将 XML 反序列化为对象图。该 XML 可以采用 DOM 文档,Importing 或输出流或 SAX 处理程序的形式。
使用 Spring 满足 O/XMap 需求的一些好处是:
21.1.1 易于配置
Spring 的 bean 工厂使配置封送程序变得容易,而无需构造 JAXB 上下文,JiBX 绑定工厂等。封送程序可以配置为应用程序上下文中的任何其他 bean。此外,许多编组人员都可以使用基于 XML 名称空间的配置,从而使配置更加简单。
21.1.2 一致的界面
Spring 的 O/XMap 通过两个全局接口进行操作:Marshaller
和Unmarshaller
接口。这些抽象使您可以相对轻松地切换 O/XMap 框架,而对编组的类几乎不需要更改。这种方法的另一个好处是,可以利用每种技术的优势,以非介入方式使用混合匹配方法(例如,使用 JAXB 进行某些编组,而其他使用 XMLBeans 进行)进行 XML 编组。
21.1.3 一致的异常层次结构
Spring 提供了从底层 O/XMap 工具的异常到其自己的异常层次的转换,并以XmlMappingException
作为根异常。可以预期,这些运行时异常包装了原始异常,因此不会丢失任何信息。
21.2 编组和解组
如引言中所述,* marshaller 将对象序列化为 XML,而 unmarshaller *将 XML 流反序列化为对象。在本节中,我们将描述用于此目的的两个 Spring 接口。
21.2.1 Marshaller
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
。结果是一个标记接口,该接口基本上表示 XML 输出抽象:具体实现包装了各种 XML 表示形式,如下表所示。
Result implementation | 包装 XML 表示形式 |
---|---|
DOMResult |
org.w3c.dom.Node |
SAXResult |
org.xml.sax.ContentHandler |
StreamResult |
java.io.File ,java.io.OutputStream 或java.io.Writer |
Note
尽管marshal()
方法接受一个普通对象作为其第一个参数,但是大多数Marshaller
实现无法处理任意对象。相反,必须将对象类 Map 到 Map 文件中,并用注解标记,在编组器中注册或具有公共 Base Class。请参阅本章的其他部分,以确定您选择的 O/X 技术如何 Management 此内容。
21.2.2 Unmarshaller
与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
(XMLImporting 抽象)中读取并返回读取的对象。与 Result 一样,Source 是具有三个具体实现的标记接口。每种包装不同的 XML 表示形式,如下表所示。
Source implementation | 包装 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
中的编组和解组类。
21.2.3 XmlMappingException
Spring 使用XmlMappingException
作为根异常将底层 O/XMap 工具中的异常转换为它自己的异常层次结构。可以预期,这些运行时异常包装了原始异常,因此不会丢失任何信息。
此外,MarshallingFailureException
和UnmarshallingFailureException
提供了编组和解组操作之间的区别,即使基础的 O/XMap 工具没有这样做。
O/XMap 异常层次结构如下图所示:
O/XMap 异常层次结构
21.3 使用 Marshaller 和 Unmarshaller
Spring 的 OXM 可用于多种情况。在下面的示例中,我们将使用它来将 Spring 托管应用程序的设置作为 XML 文件进行编组。我们将使用一个简单的 JavaBean 来表示设置:
public class Settings {
private boolean fooEnabled;
public boolean isFooEnabled() {
return fooEnabled;
}
public void setFooEnabled(boolean fooEnabled) {
this.fooEnabled = fooEnabled;
}
}
应用程序类使用此 bean 存储其设置。除了主要方法外,该类还有两个方法: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"/>
21.4 XML 配置名称空间
可以使用 OXM 名称空间中的标签更简洁地配置 Marshallers。为了使这些标签可用,必须首先在 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"/>
21.5 JAXB
JAXB 绑定编译器将 W3C XML Schema 转换为一个或多个 Java 类,一个jaxb.properties
文件以及可能的一些资源文件。 JAXB 还提供了一种从带 Comments 的 Java 类生成模式的方法。
Spring 遵循第 21.2 节“ Marshaller 和 Unmarshaller”中描述的Marshaller
和Unmarshaller
接口,将 JAXB 2.0 API 作为 XML 编组策略。相应的集成类位于org.springframework.oxm.jaxb
包中。
21.5.1 Jaxb2Marshaller
Jaxb2Marshaller
类同时实现 Spring Marshaller
和Unmarshaller
接口。它需要一个上下文路径进行操作,您可以使用contextPath
属性进行设置。上下文路径是用冒号(:)分隔的 Java 程序包名称的列表,其中包含模式派生的类。它还提供了classesToBeBound
属性,该属性使您可以设置编组支持的类的数组。通过向 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>
可用的属性有:
Attribute | Description | Required |
---|---|---|
id |
编组人员的 ID | no |
contextPath |
JAXB 上下文路径 | no |
21.6 Castor
Castor XMLMap 是一个开源 XML 绑定框架。它允许您将 Java 对象模型中包含的数据转换为 XML 文档或从 XML 文档转换。默认情况下,它不需要任何进一步的配置,尽管可以使用 Map 文件来更好地控制 Castor 的行为。
有关 Castor 的更多信息,请参阅Castor 网站。 Spring 集成类位于org.springframework.oxm.castor
包中。
21.6.1 CastorMarshaller
与 JAXB 一样,CastorMarshaller
实现Marshaller
和Unmarshaller
接口。可以如下进行连接:
<beans>
<bean id="castorMarshaller" class="org.springframework.oxm.castor.CastorMarshaller" />
...
</beans>
21.6.2 Mapping
尽管可以依赖 Castor 的默认编组行为,但可能有必要对其进行更多控制。这可以使用 CastorMap 文件来完成。有关更多信息,请参阅Castor XMLMap。
可以使用mappingLocation
资源属性来设置 Map,该属性在下面用 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"/>
通过指定 Map 文件的位置(通过mapping-location
属性)或标识存在相应 XMLDescriptors 类的 Java POJO(通过target-class
或target-package
属性),可以通过两种方式配置编组实例。后一种方法通常与从 XML 模式生成 XML 代码结合使用。
可用的属性有:
Attribute | Description | Required |
---|---|---|
id |
编组人员的 ID | no |
encoding |
用于从 XML 解组的编码 | no |
target-class |
POJO 的 Java 类名,该类具有 XML 类 Descriptors(通过代码生成生成) | no |
target-package |
Java 包名称,用于标识包含 POJO 及其对应的 Castor XMLDescriptors 类的包(由 XML 模式生成的代码生成) | no |
mapping-location |
Castor XMLMap 文件的位置 | no |
21.7 XMLBeans
XMLBeans 是一种 XML 绑定工具,具有完整的 XML Schema 支持,并提供完整的 XML Infoset 保真度。它与大多数其他 O/XMap 框架采用的方法不同,因为从 XML Schema 生成的所有类都源自XmlObject
,并且其中包含 XML 绑定信息。
有关 XMLBeans 的更多信息,请参考XMLBeans 网站。 Spring-WS 集成类位于org.springframework.oxm.xmlbeans
包中。
21.7.1 XmlBeansMarshaller
XmlBeansMarshaller
同时实现Marshaller
和Unmarshaller
接口。可以配置如下:
<beans>
<bean id="xmlBeansMarshaller" class="org.springframework.oxm.xmlbeans.XmlBeansMarshaller" />
...
</beans>
Note
请注意,XmlBeansMarshaller
只能封送XmlObject
类型的对象,而不能封送每个java.lang.Object
。
XML 配置名称空间
xmlbeans-marshaller
标签配置org.springframework.oxm.xmlbeans.XmlBeansMarshaller
。这是一个例子:
<oxm:xmlbeans-marshaller id="marshaller"/>
可用的属性有:
Attribute | Description | Required |
---|---|---|
id |
编组人员的 ID | no |
options |
用于此编组器的 XmlOptions 的 bean 名称。通常为XmlOptionsFactoryBean 定义 |
no |
21.8 JiBX
JiBX 框架提供了类似于 JDO 为 ORM 提供的解决方案:绑定定义定义了 Java 对象如何与 XML 相互转换的规则。在准备好绑定并编译了类之后,JiBX 绑定编译器将增强类文件,并添加代码以处理将类的实例从 XML 转换为 XML 的过程。
有关 JiBX 的更多信息,请参考JiBX 网站。 Spring 集成类位于org.springframework.oxm.jibx
包中。
21.8.1 JibxMarshaller
JibxMarshaller
类同时实现Marshaller
和Unmarshaller
接口。要进行操作,需要 Importing 要编组的类的名称,您可以使用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"/>
可用的属性有:
Attribute | Description | Required |
---|---|---|
id |
编组人员的 ID | no |
target-class |
该编组的目标类 | yes |
bindingName |
该编组使用的绑定名称 | no |
21.9 XStream
XStream 是一个简单的库,用于将对象序列化为 XML 并再次返回。它不需要任何 Map,并生成干净的 XML。
有关 XStream 的更多信息,请参考XStream 网站。 Spring 集成类位于org.springframework.oxm.xstream
包中。
21.9.1 XStreamMarshaller
XStreamMarshaller
不需要任何配置,可以直接在应用程序上下文中进行配置。要进一步自定义 XML,可以设置* alias map *,它由 Map 到类的字符串别名组成:
<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>
Warning
默认情况下,XStream 允许解组任意类,这会导致不安全的 Java 序列化效果。因此,不建议使用XStreamMarshaller
来从外部来源(即 Web)解组 XML,因为这可能会导致安全漏洞*。
如果您选择使用XStreamMarshaller
从外部源中解组 XML,请在XStreamMarshaller
上设置supportedClasses
属性,如下所示:
<bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="supportedClasses" value="org.springframework.oxm.xstream.Flight"/>
...
</bean>
这样可以确保只有注册的类才有资格进行编组。
此外,您可以注册custom converters以确保只能解组受支持的类。除了显式支持应支持的域类的转换器之外,您可能还想添加CatchAllConverter
作为列表中的最后一个转换器。结果,不会调用具有较低优先级和可能的安全漏洞的默认 XStream 转换器。
Note
请注意,XStream 是 XML 序列化库,而不是数据绑定库。因此,它具有有限的名称空间支持。因此,它非常不适合在 Web 服务中使用。