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

使用对象 XML 映射器封送 XML

介绍

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

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

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

易于配置

Spring 的 bean factory 使配置编组器变得容易,而无需 构造 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,解组器将 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()method 接受一个 plain object 作为其第一个参数,则大多数Marshallerimplementations 无法处理任意对象。相反,对象类 必须在映射文件中映射,使用注释进行标记,并使用 marshaller 或具有公共基类。请参阅本章后面的章节 来确定您的 O-X 技术如何管理这一点。

理解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 中的所有实现都在一个类中实现两者。 这意味着您可以连接一个 marshaller 类,并将其同时称为 marshaller 并作为 unmarshaller in yourapplicationContext.xml.spring-doc.cadn.net.cn

理解XmlMappingException

Spring 将来自底层 O-X 映射工具的异常转换为它自己的异常 hierarchy 替换为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 Management 的应用程序的设置编组为 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
}

application 类使用此 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()
}

The Application requires both a marshaller and an unmarshaller property to be set. We can do so by using the following 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>

This application context uses XStream, but we could have used any of the other marshaller instances described later in this chapter. Note that, by default, XStream does not require any further configuration, so the bean definition is rather simple. Also note that the XStreamMarshaller implements both Marshaller and Unmarshaller, so we can refer to the xstreamMarshaller bean in both the marshaller and unmarshaller property of the application.spring-doc.cadn.net.cn

This sample application produces the following settings.xml file:spring-doc.cadn.net.cn

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

XML Configuration Namespace

You can configure marshallers more concisely by using tags from the OXM namespace. To make these tags available, you must first reference the appropriate schema in the preamble of the XML configuration file. The following example shows how to do so: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 Reference the oxm schema.
2 Specify the oxm schema location.

The schema makes the following elements available:spring-doc.cadn.net.cn

Each tag is explained in its respective marshaller’s section. As an example, though, the configuration of a JAXB2 marshaller might resemble the following:spring-doc.cadn.net.cn

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

JAXB

The JAXB binding compiler translates a W3C XML Schema into one or more Java classes, a jaxb.properties file, and possibly some resource files. JAXB also offers a way to generate a schema from annotated Java classes.spring-doc.cadn.net.cn

Spring supports the JAXB 2.0 API as XML marshalling strategies, following the Marshaller and Unmarshaller interfaces described in Marshaller and Unmarshaller. The corresponding integration classes reside in the org.springframework.oxm.jaxb package.spring-doc.cadn.net.cn

Using Jaxb2Marshaller

The Jaxb2Marshaller class implements both of Spring’s Marshaller and Unmarshaller interfaces. It requires a context path to operate. You can set the context path by setting the contextPath property. The context path is a list of colon-separated Java package names that contain schema derived classes. It also offers a classesToBeBound property, which allows you to set an array of classes to be supported by the marshaller. Schema validation is performed by specifying one or more schema resources to the bean, as the following example shows: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 Configuration Namespace

The jaxb2-marshaller element configures a org.springframework.oxm.jaxb.Jaxb2Marshaller, as the following example shows:spring-doc.cadn.net.cn

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

Alternatively, you can provide the list of classes to bind to the marshaller by using the class-to-be-bound child element: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>

The following table describes the available attributes:spring-doc.cadn.net.cn

Attribute Description Required

idspring-doc.cadn.net.cn

The ID of the marshallerspring-doc.cadn.net.cn

Nospring-doc.cadn.net.cn

contextPathspring-doc.cadn.net.cn

The JAXB Context pathspring-doc.cadn.net.cn

Nospring-doc.cadn.net.cn

JiBX

The JiBX framework offers a solution similar to that which Hibernate provides for ORM: A binding definition defines the rules for how your Java objects are converted to or from XML. After preparing the binding and compiling the classes, a JiBX binding compiler enhances the class files and adds code to handle converting instances of the classes from or to XML.spring-doc.cadn.net.cn

For more information on JiBX, see the JiBX web site. The Spring integration classes reside in the org.springframework.oxm.jibx package.spring-doc.cadn.net.cn

Using JibxMarshaller

The JibxMarshaller class implements both the Marshaller and Unmarshaller interface. To operate, it requires the name of the class to marshal in, which you can set using the targetClass property. Optionally, you can set the binding name by setting the bindingName property. In the following example, we bind the Flights class: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>

A JibxMarshaller is configured for a single class. If you want to marshal multiple classes, you have to configure multiple JibxMarshaller instances with different targetClass property values.spring-doc.cadn.net.cn

XML Configuration Namespace

The jibx-marshaller tag configures a org.springframework.oxm.jibx.JibxMarshaller, as the following example shows:spring-doc.cadn.net.cn

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

The following table describes the available attributes:spring-doc.cadn.net.cn

Attribute Description Required

idspring-doc.cadn.net.cn

The ID of the marshallerspring-doc.cadn.net.cn

Nospring-doc.cadn.net.cn

target-classspring-doc.cadn.net.cn

The target class for this marshallerspring-doc.cadn.net.cn

Yesspring-doc.cadn.net.cn

bindingNamespring-doc.cadn.net.cn

The binding name used by this marshallerspring-doc.cadn.net.cn

Nospring-doc.cadn.net.cn

XStream

XStream is a simple library to serialize objects to XML and back again. It does not require any mapping and generates clean XML.spring-doc.cadn.net.cn

For more information on XStream, see the XStream web site. The Spring integration classes reside in the org.springframework.oxm.xstream package.spring-doc.cadn.net.cn

Using XStreamMarshaller

The XStreamMarshaller does not require any configuration and can be configured in an application context directly. To further customize the XML, you can set an alias map, which consists of string aliases mapped to classes, as the following example shows: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>

By default, XStream lets arbitrary classes be unmarshalled, which can lead to unsafe Java serialization effects. As such, we do not recommend using the XStreamMarshaller to unmarshal XML from external sources (that is, the Web), as this can result in security vulnerabilities.spring-doc.cadn.net.cn

If you choose to use the XStreamMarshaller to unmarshal XML from an external source, set the supportedClasses property on the XStreamMarshaller, as the following example shows:spring-doc.cadn.net.cn

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

Doing so ensures that only the registered classes are eligible for unmarshalling.spring-doc.cadn.net.cn

Additionally, you can register custom converters to make sure that only your supported classes can be unmarshalled. You might want to add a CatchAllConverter as the last converter in the list, in addition to converters that explicitly support the domain classes that should be supported. As a result, default XStream converters with lower priorities and possible security vulnerabilities do not get invoked.spring-doc.cadn.net.cn

Note that XStream is an XML serialization library, not a data binding library. Therefore, it has limited namespace support. As a result, it is rather unsuitable for usage within Web Services.