此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring Framework 6.2.10spring-doc.cadn.net.cn

使用 Object-XML 映射器封送 XML

介绍

本章介绍了 Spring 的 Object-XML Mapping 支持。对象-XML 映射(简称 O-X 映射)是将 XML 文档与 XML 文档进行转换和从中转换的行为 一个对象。此转换过程也称为 XML 封送处理或 XML 序列化。本章可以互换使用这些术语。spring-doc.cadn.net.cn

在 O-X 映射领域中,封送程序负责序列化 对象(图形)转换为 XML。以类似的方式,unmarshaller 将 XML 反序列化为 对象图。此 XML 可以采用 DOM 文档、输入或输出的形式 流或 SAX 处理程序。spring-doc.cadn.net.cn

使用 Spring 满足 O/X 映射需求的一些好处是:spring-doc.cadn.net.cn

易于配置

Spring 的 bean 工厂可以轻松配置封送程序,而无需 构造 JAXB 上下文、JiBX 绑定工厂等。您可以配置封送程序 就像处理应用程序上下文中的任何其他 Bean 一样。此外,基于 XML 命名空间的 配置可用于许多编组程序,使配置均匀 简单。spring-doc.cadn.net.cn

一致的接口

Spring 的 O-X 映射通过两个全局接口运行:MarshallerUnmarshaller.这些抽象允许您切换 O-X 映射框架 相对容易,对执行 编组。这种方法还有一个额外的好处,那就是可以执行 XML 使用混合和匹配方法进行编组(例如,使用 JAXB 执行的一些编组 有些由 XStream 提供),让您以非侵入式方式使用每个 科技。spring-doc.cadn.net.cn

一致的异常层次结构

Spring 提供了从底层 O-X 映射工具到其 自己的异常层次结构,并带有XmlMappingException作为根异常。 这些运行时异常包装原始异常,因此不会丢失任何信息。spring-doc.cadn.net.cn

MarshallerUnmarshaller

简介中所述,封送器序列化对象 到 XML,unmarshaller 将 XML 流反序列化为对象。本节介绍 用于此目的的两个 Spring 接口。spring-doc.cadn.net.cn

理解Marshaller

Spring 抽象了org.springframework.oxm.Marshaller接口,其主要方法如下:spring-doc.cadn.net.cn

public interface Marshaller {

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

Marshallerinterface 有一个 main 方法,它将给定对象封送到一个 鉴于javax.xml.transform.Result.结果是一个标记接口,基本上 表示 XML 输出抽象。具体实现包装各种 XML 表示形式,如下表所示:spring-doc.cadn.net.cn

结果实现 包装 XML 表示

DOMResultspring-doc.cadn.net.cn

org.w3c.dom.Nodespring-doc.cadn.net.cn

SAXResultspring-doc.cadn.net.cn

org.xml.sax.ContentHandlerspring-doc.cadn.net.cn

StreamResultspring-doc.cadn.net.cn

java.io.File,java.io.OutputStreamjava.io.Writerspring-doc.cadn.net.cn

尽管marshal()方法接受一个普通对象作为其第一个参数,大多数Marshaller实现不能处理任意对象。相反,对象类 必须映射到映射文件中,用注释标记,向 marshaller,或者具有公共基类。请参阅本章的后面部分 以确定您的 OX 技术如何管理这一点。

理解Unmarshaller

类似于Marshaller,我们有org.springframework.oxm.Unmarshaller界面,如下表所示:spring-doc.cadn.net.cn

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 表示形式,如下表所示:spring-doc.cadn.net.cn

源实现 包装 XML 表示

DOMSourcespring-doc.cadn.net.cn

org.w3c.dom.Nodespring-doc.cadn.net.cn

SAXSourcespring-doc.cadn.net.cn

org.xml.sax.InputSourceorg.xml.sax.XMLReaderspring-doc.cadn.net.cn

StreamSourcespring-doc.cadn.net.cn

java.io.File,java.io.InputStreamjava.io.Readerspring-doc.cadn.net.cn

即使有两个单独的封送接口 (MarshallerUnmarshaller),Spring-WS 中的所有实现都在一个类中实现。 这意味着您可以连接一个封送程序类,并将其都称为 编组者和作为 unmarshallerapplicationContext.xml.spring-doc.cadn.net.cn

理解XmlMappingException

Spring 将异常从底层 OX 映射工具转换为自己的异常 层次结构与XmlMappingException作为根异常。 这些运行时异常包装原始异常,因此不会丢失任何信息。spring-doc.cadn.net.cn

此外,MarshallingFailureExceptionUnmarshallingFailureException提供封送作和取消封送作之间的区别,即使 底层 O-X 映射工具不这样做。spring-doc.cadn.net.cn

O-X 映射异常层次结构如下图所示:spring-doc.cadn.net.cn

oxm 异常

MarshallerUnmarshaller

您可以在各种情况下使用 Spring 的 OXM。在下面的示例中,我们 使用它将 Spring 管理的应用程序的设置编组为 XML 文件。在下面的示例中,我们 使用简单的 JavaBean 来表示设置:spring-doc.cadn.net.cn

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 来存储其设置。除了一个 main 方法之外,class 还有两个方法:saveSettings()将设置 bean 保存到名为settings.xmlloadSettings()再次加载这些设置。以下内容main()方法 构造一个 Spring 应用程序上下文并调用以下两个方法:spring-doc.cadn.net.cn

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需要同时marshallerunmarshaller属性。我们 可以使用以下命令来实现此目的applicationContext.xml:spring-doc.cadn.net.cn

<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,但我们可以使用任何其他封送程序 本章后面将描述的实例。请注意,默认情况下,XStream 不需要 任何进一步的配置,因此 bean 定义相当简单。另请注意,XStreamMarshaller实现两者MarshallerUnmarshaller,所以我们可以参考xstreamMarshallerbean 在marshallerunmarshaller属性的 应用。spring-doc.cadn.net.cn

此示例应用程序生成以下内容settings.xml文件:spring-doc.cadn.net.cn

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

XML 配置命名空间

您可以使用 OXM 命名空间中的标记更简洁地配置封送程序。 要使这些标记可用,您必须首先在 XML 配置文件的前导码。以下示例显示了如何执行此作:spring-doc.cadn.net.cn

<?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模式位置。

架构使以下元素可用:spring-doc.cadn.net.cn

每个标记在其各自的封送程序部分中都有说明。不过,作为一个例子, JAXB2 封送程序的配置可能类似于以下内容:spring-doc.cadn.net.cn

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

JAXB

JAXB 绑定编译器将 W3C XML 模式转换为一个或多个 Java 类,即jaxb.properties文件,可能还有一些资源文件。JAXB 还提供了一种方法 从带注释的 Java 类生成模式。spring-doc.cadn.net.cn

Spring 支持 JAXB 2.0 API 作为 XML 编组策略,遵循MarshallerUnmarshaller中描述的接口MarshallerUnmarshaller. 相应的集成类驻留在org.springframework.oxm.jaxb包。spring-doc.cadn.net.cn

Jaxb2Marshaller

Jaxb2Marshallerclass 实现了 Spring 的MarshallerUnmarshaller接口。它需要上下文路径才能运行。您可以通过设置contextPath财产。上下文路径是冒号分隔的 Java 包列表 包含架构派生类的名称。它还提供了一个classesToBeBound财产 它允许您设置封送处理程序要支持的类数组。图式 通过向 Bean 指定一个或多个模式资源来执行验证,如以下示例所示:spring-doc.cadn.net.cn

<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, 如以下示例所示:spring-doc.cadn.net.cn

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

或者,可以使用class-to-be-boundchild 元素:spring-doc.cadn.net.cn

<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>

下表描述了可用属性:spring-doc.cadn.net.cn

属性 描述 必填

idspring-doc.cadn.net.cn

封送程序的 IDspring-doc.cadn.net.cn

spring-doc.cadn.net.cn

contextPathspring-doc.cadn.net.cn

JAXB 上下文路径spring-doc.cadn.net.cn

spring-doc.cadn.net.cn

吉布克斯

JiBX 框架提供了一个类似于 Hibernate 为 ORM 提供的解决方案:一个 绑定定义定义了如何将 Java 对象转换为 Java 对象或从 Java 对象转换的规则 准备好绑定并编译类后,JiBX 绑定编译器 增强类文件并添加代码来处理类的转换实例 from 或 to XML。spring-doc.cadn.net.cn

有关 JiBX 的更多信息,请参阅 JiBX Web 网站。Spring 集成类驻留在org.springframework.oxm.jibx包。spring-doc.cadn.net.cn

JibxMarshaller

JibxMarshaller类实现了MarshallerUnmarshaller接口。 要作,它需要要封送的类的名称,您可以使用该名称使用targetClass财产。 或者,您可以通过设置bindingName财产。 在下面的示例中,我们将Flights类:spring-doc.cadn.net.cn

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

一个JibxMarshaller为单个类配置。如果要封送多个类,则必须配置多个JibxMarshaller具有不同targetClass属性值。spring-doc.cadn.net.cn

XML 配置命名空间

jibx-marshaller标记配置一个org.springframework.oxm.jibx.JibxMarshaller, 如以下示例所示:spring-doc.cadn.net.cn

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

下表描述了可用属性:spring-doc.cadn.net.cn

属性 描述 必填

idspring-doc.cadn.net.cn

封送程序的 IDspring-doc.cadn.net.cn

spring-doc.cadn.net.cn

target-classspring-doc.cadn.net.cn

此封送程序的目标类spring-doc.cadn.net.cn

是的spring-doc.cadn.net.cn

bindingNamespring-doc.cadn.net.cn

此封送程序使用的绑定名称spring-doc.cadn.net.cn

spring-doc.cadn.net.cn

X斯特里姆

XStream 是一个简单的库,用于将对象序列化为 XML,然后再序列化回来。它不会 需要任何映射并生成干净的 XML。spring-doc.cadn.net.cn

有关 XStream 的详细信息,请参阅 XStream 网站。Spring 集成类驻留在org.springframework.oxm.xstream包。spring-doc.cadn.net.cn

XStreamMarshaller

XStreamMarshaller不需要任何配置,可以在 应用程序上下文。要进一步自定义 XML,您可以设置别名映射 它由映射到类的字符串别名组成,如以下示例所示:spring-doc.cadn.net.cn

<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 序列化效果。因此,我们不建议使用XStreamMarshaller从外部源(即 Web)取消封送 XML,因为这可以 导致安全漏洞。spring-doc.cadn.net.cn

如果您选择使用XStreamMarshaller从外部源取消封送 XML, 将supportedClasses属性XStreamMarshaller,如以下示例所示:spring-doc.cadn.net.cn

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

这样做可以确保只有注册的类才有资格进行解组。spring-doc.cadn.net.cn

此外,您可以注册自定义转换器,以确保只有您支持的类才能解组。你可能想要 添加一个CatchAllConverter作为列表中的最后一个转换器,除了 显式支持应支持的域类的转换器。 因此,默认的 XStream 转换器具有较低的优先级和可能的安全性 不会调用漏洞。spring-doc.cadn.net.cn

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