此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Framework 6.2.4! |
使用对象 XML 映射器封送 XML
介绍
本章描述了 Spring 的 Object-XML Mapping 支持。对象 XML 映射(简称 O-X 映射)是将 XML 文档相互转换的过程 一个对象。此转换过程也称为 XML 封送或 XML 序列化。本章可以互换使用这些术语。
在 O-X 映射领域中,编组器负责序列化 object (graph) 转换为 XML。以类似的方式,解组器将 XML 反序列化为 对象图。此 XML 可以采用 DOM 文档、输入或输出的形式 stream 或 SAX 处理程序。
使用 Spring 满足您的 O/X 映射需求的一些好处是:
易于配置
Spring 的 bean factory 使配置编组器变得容易,而无需 构造 JAXB 上下文、JiBX 绑定工厂等。您可以配置封送处理程序 就像您在应用程序上下文中的任何其他 bean 一样。此外,基于 XML 命名空间 配置可用于许多编组器,使配置均匀 简单。
一致的接口
Spring 的 O-X 映射通过两个全局接口运行:Marshaller
和Unmarshaller
.这些抽象允许您切换 O-X 映射框架
相对容易,只需对执行
编组。这种方法还有一个额外的好处,就是可以执行 XML
使用混合匹配方法进行封送(例如,使用 JAXB 执行一些封送处理
还有一些由 XStream 提供),让您使用每个
科技。
Marshaller
和Unmarshaller
如简介中所述,编组处理程序序列化对象 转换为 XML,解组器将 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;
}
这Marshaller
interface 有一个 main 方法,该方法将给定对象封送到
鉴于javax.xml.transform.Result
.结果是一个标记接口,基本上
表示 XML 输出抽象。具体实现包装各种 XML
表示形式,如下表所示:
结果实现 | 包装 XML 表示 |
---|---|
|
|
|
|
|
|
尽管marshal() method 接受一个 plain object 作为其第一个参数,则大多数Marshaller implementations 无法处理任意对象。相反,对象类
必须在映射文件中映射,使用注释进行标记,并使用
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 中的所有实现都在一个类中实现两者。
这意味着您可以连接一个 marshaller 类,并将其同时称为
marshaller 并作为 unmarshaller in yourapplicationContext.xml
.
用Marshaller
和Unmarshaller
您可以将 Spring 的 OXM 用于各种情况。在下面的示例中,我们 使用它可将 Spring Management 的应用程序的设置编组为 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
}
application 类使用此 bean 来存储其设置。除了 main 方法之外,
class 有两种方法: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()
}
The Application
requires both a marshaller
and an unmarshaller
property to be set. We
can do so by using the following 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>
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.
This sample application produces the following settings.xml
file:
<?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:
<?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:
Each tag is explained in its respective marshaller’s section. As an example, though,
the configuration of a JAXB2 marshaller might resemble the following:
<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 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.
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:
<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:
<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:
<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:
Attribute
Description
Required
id
The ID of the marshaller
No
contextPath
The JAXB Context path
No
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.
For more information on JiBX, see the JiBX web
site. The Spring integration classes reside in the org.springframework.oxm.jibx
package.
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:
<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.
XML Configuration Namespace
The jibx-marshaller
tag configures a org.springframework.oxm.jibx.JibxMarshaller
,
as the following example shows:
<oxm:jibx-marshaller id="marshaller" target-class="org.springframework.ws.samples.airline.schema.Flight"/>
The following table describes the available attributes:
Attribute
Description
Required
id
The ID of the marshaller
No
target-class
The target class for this marshaller
Yes
bindingName
The binding name used by this marshaller
No
XStream
XStream is a simple library to serialize objects to XML and back again. It does not
require any mapping and generates clean XML.
For more information on XStream, see the XStream
web site. The Spring integration classes reside in the
org.springframework.oxm.xstream
package.
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:
<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.
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:
<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.
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.
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.