|
对于最新的稳定版本,请使用 Spring Framework 7.0.6! |
使用对象-XML映射器实现XML编组
简介
本章描述了Spring的面向对象-XML映射支持。面向对象-XML映射(简称O-X映射)是指将XML文档与对象之间进行转换的行为。这个转换过程也被称为XML打包,或XML序列化。本章中这些术语会交替使用。
在O-X映射领域,marshaller负责将对象(图)序列化为XML。以类似的方式,Unmarshaller将XML反序列化为对象图。此XML可以是DOM文档、输入或输出流,或者SAX处理器的形式。
使用 Spring 满足您的 O/X 映射需求的一些好处包括:
配置简便性
Spring的bean工厂使得配置marshaller变得很容易,而无需构造JAXB上下文、JiBX绑定工厂等。你可以像配置应用程序上下文中的其他bean一样配置marshaller。此外,许多marshaller还提供了基于XML命名空间的配置方式,使配置更加简单。
一致接口
Spring的O-X映射通过两个全局接口进行操作:Marshaller和Unmarshaller。这些抽象使您能够相对轻松地在O-X映射框架之间切换,对执行序列化的类几乎不需要或不需要任何更改。这种方法的另一个优点是,可以以混合搭配的方式进行XML序列化(例如,一些序列化使用JAXB,另一些使用XStream),并且是以非侵入性的方式进行的,使您可以利用每种技术的优势。
Marshaller 和 Unmarshaller
如< a t="C0">简介中所述,marshaller 将对象序列化为 XML,而 unmarshaller 将 XML 流反序列化为对象。本节将介绍用于此目的的两个 Spring 接口。
了解 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;
}
The Marshaller interface 有一个主要方法,该方法将给定的对象转换为给定的 javax.xml.transform.Result。结果是一个标记接口,基本上表示 XML 输出抽象。具体的实现包装了各种 XML 表示形式,如下表所示:
| 结果实现 | 包装 XML 表示形式 |
|---|---|
|
|
|
|
|
|
虽然 marshal() 方法接受一个普通对象作为其第一个参数,但大多数
Marshaller 实现无法处理任意对象。相反,必须在映射文件中映射对象类,或用注解标记该对象,或将其注册到marshaller 中,或者该对象必须有一个公共的基类。请参阅本章后面的章节,以确定您的 O-X 技术如何处理此问题。 |
了解 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(XML输入抽象)读取并返回读取的对象。与
Result一样,Source是一个标记接口,有三个具体的实现类。每个实现类都包装了不同的XML表示形式,如下面的表格所示:
| 源代码实现 | 包装 XML 表示形式 |
|---|---|
|
|
|
|
|
|
尽管有两个独立的序列化接口(Marshaller 和 Unmarshaller),但 Spring-WS 中的所有实现都将在一个类中同时实现这两个接口。
这意味着您可以配置一个序列化器类,并在您的 applicationContext.xml 中将其同时作为序列化器和反序列化器引用。
使用 Marshaller 和 Unmarshaller
你可以使用 Spring 的 OXM 用于各种情况。在下面的例子中,我们使用它将 Spring 管理的应用程序的设置作为 XML 文件进行序列化。在下面的例子中,我们使用一个简单的 JavaBean 来表示这些设置:
-
Java
-
Kotlin
public class Settings {
private boolean fooEnabled;
public boolean isFooEnabled() {
return fooEnabled;
}
public void setFooEnabled(boolean fooEnabled) {
this.fooEnabled = fooEnabled;
}
}
class Settings {
var isFooEnabled: Boolean = false
}
应用程序类使用此bean来存储其设置。除了主方法外,该类还有两个方法: saveSettings() 将设置bean保存到名为 settings.xml 的文件中,而 loadSettings() 会重新加载这些设置。以下 main() 方法构建一个Spring应用上下文并调用这两个方法:
-
Java
-
Kotlin
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 {
try (FileOutputStream os = new FileOutputStream(FILE_NAME)) {
this.marshaller.marshal(settings, new StreamResult(os));
}
}
public void loadSettings() throws IOException {
try (FileInputStream is = new FileInputStream(FILE_NAME)) {
this.settings = (Settings) this.unmarshaller.unmarshal(new StreamSource(is));
}
}
public static void main(String[] args) throws IOException {
ApplicationContext appContext =
new ClassPathXmlApplicationContext("applicationContext.xml");
Application application = (Application) appContext.getBean("application");
application.saveSettings();
application.loadSettings();
}
}
class Application {
lateinit var marshaller: Marshaller
lateinit var unmarshaller: Unmarshaller
fun saveSettings() {
FileOutputStream(FILE_NAME).use { outputStream -> marshaller.marshal(settings, StreamResult(outputStream)) }
}
fun loadSettings() {
FileInputStream(FILE_NAME).use { inputStream -> settings = unmarshaller.unmarshal(StreamSource(inputStream)) as Settings }
}
}
private const val FILE_NAME = "settings.xml"
fun main(args: Array<String>) {
val appContext = ClassPathXmlApplicationContext("applicationContext.xml")
val application = appContext.getBean("application") as Application
application.saveSettings()
application.loadSettings()
}
Application 需要同时设置 marshaller 和 unmarshaller 属性。我们可以通过使用以下 applicationContext.xml 来实现:
<beans>
<bean id="application" class="Application">
<property name="marshaller" ref="xstreamMarshaller" />
<property name="unmarshaller" ref="xstreamMarshaller" />
</bean>
<bean id="xstreamMarshaller" class="org.springframework.oxm.xstream.XStreamMarshaller"/>
</beans>
此应用上下文使用XStream,但我们可以使用本章后面描述的任何其他marshaller实例。请注意,默认情况下,XStream不需要任何进一步的配置,因此bean定义相当简单。还要注意,XStreamMarshaller同时实现了Marshaller和Unmarshaller,因此我们可以在应用的marshaller和unmarshaller属性中引用xstreamMarshaller bean。
此示例应用程序生成以下 settings.xml 文件:
<?xml version="1.0" encoding="UTF-8"?>
<settings foo-enabled="false"/>
XML 配置命名空间
你可以通过使用OXM命名空间中的标签更简洁地配置marshaller。 要使这些标签可用,你必须首先在XML配置文件的开头引用相应的模式。下面的例子展示了如何操作:
<?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" (1)
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/oxm
https://www.springframework.org/schema/oxm/spring-oxm.xsd"> (2)
| 1 | 引用 oxm 模式。 |
| 2 | 指定 oxm 架构位置。 |
该模式提供了以下元素:
每个标签都在其对应的marshaller部分中进行了说明。例如,尽管如此,JAXB2 marshaller的配置可能如下所示:
<oxm:jaxb2-marshaller id="marshaller" contextPath="org.springframework.ws.samples.airline.schema"/>
JAXB
JAXB 绑定编译器将 W3C XML 模式转换为一个或多个 Java 类、一个
jaxb.properties 文件,以及可能的一些资源文件。JAXB 还提供了一种从带注解的 Java 类生成模式的方法。
Spring 支持 JAXB 2.0 API 作为 XML 序列化策略,遵循在 Marshaller 和 Unmarshaller 中描述的 Marshaller 和 Unmarshaller 接口。
相应的集成类位于 org.springframework.oxm.jaxb 包中。
使用 Jaxb2Marshaller
Jaxb2Marshaller 类实现了 Spring 的 Marshaller 和 Unmarshaller 接口。它需要一个上下文路径才能运行。您可以通过设置 contextPath 属性来设置上下文路径。上下文路径是由冒号分隔的 Java 包名称列表,这些包包含派生的模式类。它还提供了一个 classesToBeBound 属性,允许您设置由 marshaller 支持的类数组。通过向 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子元素来提供要绑定到marshaller的类列表:
<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>
下表描述了可用的属性:
| 属性 | 描述 | 必填 |
|---|---|---|
|
marshaller 的 ID |
No |
|
JAXB 上下文路径 |
No |
JiBX
JiBX 框架提供了一个类似于 Hibernate 为 ORM 提供的解决方案:一个绑定定义规定了您的 Java 对象如何转换为 XML 或从 XML 转换的规则。在准备绑定并编译类之后,JiBX 绑定编译器会增强类文件,并添加代码以处理将类的实例转换为 XML 或从 XML 转换的处理。
有关JiBX的更多信息,请参阅 JiBX网站。Spring集成类位于 org.springframework.oxm.jibx
包中。
使用 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 用于配置单个类。如果您想要对多个类进行序列化,必须配置多个 JibxMarshaller 实例,并使用不同的 targetClass
属性值。
XML 配置命名空间
jibx-marshaller 标签将 org.springframework.oxm.jibx.JibxMarshaller 配置为,
如下例所示:
<oxm:jibx-marshaller id="marshaller" target-class="org.springframework.ws.samples.airline.schema.Flight"/>
下表描述了可用的属性:
| 属性 | 描述 | 必填 |
|---|---|---|
|
marshaller 的 ID |
No |
|
此marshaller的目标类 |
是 |
|
此marshaller使用的绑定名称 |
No |
XStream
XStream 是一个简单的库,用于将对象序列化为 XML 并再次反序列化。它不需要任何映射,并生成干净的 XML。
有关XStream的更多信息,请参阅 XStream
网站。Spring集成类位于
org.springframework.oxm.xstream 包中。
使用 XStreamMarshaller
XStreamMarshaller 不需要任何配置,可以直接在应用上下文中进行配置。要进一步自定义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 允许任意类被反序列化,这可能导致不安全的 Java 序列化效果。因此,我们不建议使用
如果您选择使用
这样做可以确保只有已注册的类才适用于反序列化。 此外,您还可以注册
自定义
转换器,以确保只有您的支持类才能被反序列化。您可能希望在列表的最后添加一个 |
| 请注意,XStream 是一个 XML 序列化库,而不是数据绑定库。 因此,它的命名空间支持有限。结果是,它不太适合在 Web 服务中使用。 |
