转换 XML 负载
本节介绍如何转换 XML 负载
将转换器配置为 Bean
本节将解释以下转换器的运作方式以及如何将它们配置为 Bean
所有 XML 转换器都扩展了 AbstractTransformer
或 AbstractPayloadTransformer
,因此实现了 Transformer
。在 Spring Integration 中将 XML 转换器配置为 Bean 时,通常会将 Transformer
与 MessageTransformingHandler
结合配置。这使得转换器可以作为端点使用。最后,我们将讨论命名空间支持,它允许将转换器配置为 XML 中的元素。
UnmarshallingTransformer
一个 UnmarshallingTransformer
允许使用 Spring OXM 的 Unmarshaller
实现来反序列化 XML Source
。Spring 的对象/XML 映射支持提供了多种实现,支持使用 JAXB、Castor、JiBX 等进行序列化和反序列化。反序列化器需要一个 Source
实例。如果消息有效负载不是 Source
实例,则仍会尝试转换。目前,支持 String
、File
、byte[]
和 org.w3c.dom.Document
有效负载。要创建自定义的 Source
转换,您可以注入 SourceFactory
的实现。
如果您没有显式设置 SourceFactory ,则 UnmarshallingTransformer 上的属性默认设置为 DomSourceFactory .
|
从 5.0 版本开始,UnmarshallingTransformer
还支持 org.springframework.ws.mime.MimeMessage
作为传入有效负载。当我们通过 SOAP 接收带有 MTOM 附件的原始 WebServiceMessage
时,这很有用。有关更多信息,请参见 MTOM 支持.
以下示例展示了如何定义反序列化转换器
<bean id="unmarshallingTransformer" class="o.s.i.xml.transformer.UnmarshallingTransformer">
<constructor-arg>
<bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="contextPath" value="org.example" />
</bean>
</constructor-arg>
</bean>
使用 MarshallingTransformer
The MarshallingTransformer
允许使用 Spring OXM Marshaller
将对象图转换为 XML。默认情况下,MarshallingTransformer
返回 DomResult
。但是,您可以通过配置备用 ResultFactory
(例如 StringResultFactory
)来控制结果类型。在许多情况下,将有效负载转换为替代 XML 格式更方便。为此,请配置 ResultTransformer
。Spring 集成提供了两种实现,一种转换为 String
,另一种转换为 Document
。以下示例配置了一个将转换为文档的序列化转换器
<bean id="marshallingTransformer" class="o.s.i.xml.transformer.MarshallingTransformer">
<constructor-arg>
<bean class="org.springframework.oxm.jaxb.Jaxb2Marshaller">
<property name="contextPath" value="org.example"/>
</bean>
</constructor-arg>
<constructor-arg>
<bean class="o.s.i.xml.transformer.ResultToDocumentTransformer"/>
</constructor-arg>
</bean>
默认情况下,MarshallingTransformer
将有效负载对象传递给 Marshaller
。但是,如果其布尔值 extractPayload
属性设置为 false
,则整个 Message
实例将传递给 Marshaller
。这对于 Marshaller
接口的某些自定义实现可能很有用,但通常,当您委托给任何 Marshaller
实现时,有效负载是编组的适当源对象。
XsltPayloadTransformer
XsltPayloadTransformer
使用 可扩展样式表语言转换 (XSLT) 转换 XML 有效负载。转换器的构造函数需要一个 Resource 或 Templates 实例。传递 Templates
实例允许更灵活地配置用于创建模板实例的 TransformerFactory
。
与 UnmarshallingTransformer
一样,XsltPayloadTransformer
对 Source
实例执行实际的 XSLT 转换。因此,如果消息有效负载不是 Source
实例,则仍会尝试转换。String
和 Document
有效负载直接支持。
要创建对 Source
的自定义转换,您可以注入 SourceFactory
的实现。
如果未显式设置 SourceFactory ,则 XsltPayloadTransformer 上的属性默认设置为 DomSourceFactory 。
|
默认情况下,XsltPayloadTransformer
创建一个具有 Result
有效负载的消息,类似于 XmlPayloadMarshallingTransformer
。您可以通过提供 ResultFactory
或 ResultTransformer
来自定义它。
以下示例配置了一个用作 XSLT 有效负载转换器的 bean
<bean id="xsltPayloadTransformer" class="o.s.i.xml.transformer.XsltPayloadTransformer">
<constructor-arg value="classpath:org/example/xsl/transform.xsl"/>
<constructor-arg>
<bean class="o.s.i.xml.transformer.ResultToDocumentTransformer"/>
</constructor-arg>
</bean>
从 Spring Integration 3.0 开始,您可以使用构造函数参数指定转换器工厂类名。您可以通过在使用命名空间时使用 transformer-factory-class
属性来实现。
使用 ResultTransformer
实现
MarshallingTransformer
和 XsltPayloadTransformer
都允许您指定一个 ResultTransformer
。因此,如果编组或 XSLT 转换返回一个 Result
,您可以选择使用 ResultTransformer
将 Result
转换为其他格式。Spring Integration 提供了两个具体的 ResultTransformer
实现
默认情况下,MarshallingTransformer
始终返回一个 Result
。通过指定 ResultTransformer
,您可以自定义返回的有效负载类型。
XsltPayloadTransformer
的行为稍微复杂一些。默认情况下,如果输入有效负载是 String
或 Document
的实例,则会忽略 resultTransformer
属性。
但是,如果输入有效负载是 Source
或任何其他类型,则会应用 resultTransformer
属性。此外,您可以将 alwaysUseResultFactory
属性设置为 true
,这也会导致使用指定的 resultTransformer
。
有关更多信息和示例,请参阅 命名空间配置和结果转换器。
XML 转换器的命名空间支持
Spring Integration XML 命名空间中提供了对所有 XML 转换器的命名空间支持,其模板 之前已显示。转换器的命名空间支持根据提供的输入通道的类型创建 EventDrivenConsumer
或 PollingConsumer
的实例。命名空间支持旨在通过允许创建使用一个元素的端点和转换器来减少 XML 配置量。
使用 UnmarshallingTransformer
以下是UnmarshallingTransformer
的命名空间支持。由于命名空间创建的是端点实例而不是转换器,因此可以在元素内嵌套轮询器来控制输入通道的轮询。以下示例展示了如何做到这一点。
<int-xml:unmarshalling-transformer id="defaultUnmarshaller"
input-channel="input" output-channel="output"
unmarshaller="unmarshaller"/>
<int-xml:unmarshalling-transformer id="unmarshallerWithPoller"
input-channel="input" output-channel="output"
unmarshaller="unmarshaller">
<int:poller fixed-rate="2000"/>
<int-xml:unmarshalling-transformer/>
使用MarshallingTransformer
对编组转换器的命名空间支持需要一个input-channel
、一个output-channel
和一个对marshaller
的引用。可以使用可选的result-type
属性来控制创建的结果类型。有效值为StringResult
或DomResult
(默认值)。以下示例配置了一个编组转换器。
<int-xml:marshalling-transformer
input-channel="marshallingTransformerStringResultFactory"
output-channel="output"
marshaller="marshaller"
result-type="StringResult" />
<int-xml:marshalling-transformer
input-channel="marshallingTransformerWithResultTransformer"
output-channel="output"
marshaller="marshaller"
result-transformer="resultTransformer" />
<bean id="resultTransformer" class="o.s.i.xml.transformer.ResultToStringTransformer"/>
如果提供的结果类型不足,可以使用对ResultFactory
自定义实现的引用作为设置result-type
属性的替代方案,方法是使用result-factory
属性。result-type
和result-factory
属性是互斥的。
在内部,StringResult 和DomResult 结果类型分别由ResultFactory 实现表示:StringResultFactory 和DomResultFactory 。
|
使用XsltPayloadTransformer
对XsltPayloadTransformer
的命名空间支持允许您传递一个Resource
(为了创建Templates
实例)或传递一个预先创建的Templates
实例作为引用。与编组转换器一样,您可以通过指定result-factory
或result-type
属性来控制结果输出的类型。当您需要在发送之前转换结果时,可以使用result-transformer
属性来引用ResultTransformer
的实现。
如果您指定了result-factory 或result-type 属性,则底层XsltPayloadTransformer 上的alwaysUseResultFactory 属性将由XsltPayloadTransformerParser 设置为true 。
|
以下示例配置了两个XSLT转换器。
<int-xml:xslt-transformer id="xsltTransformerWithResource"
input-channel="withResourceIn" output-channel="output"
xsl-resource="org/springframework/integration/xml/config/test.xsl"/>
<int-xml:xslt-transformer id="xsltTransformerWithTemplatesAndResultTransformer"
input-channel="withTemplatesAndResultTransformerIn" output-channel="output"
xsl-templates="templates"
result-transformer="resultTransformer"/>
您可能需要访问Message
数据,例如Message
头,以帮助进行转换。例如,您可能需要访问某些Message
头并将它们作为参数传递给转换器(例如,transformer.setParameter(..)
)。Spring Integration提供了两种方便的方法来实现这一点,如下面的示例所示。
<int-xml:xslt-transformer id="paramHeadersCombo"
input-channel="paramHeadersComboChannel" output-channel="output"
xsl-resource="classpath:transformer.xslt"
xslt-param-headers="testP*, *foo, bar, baz">
<int-xml:xslt-param name="helloParameter" value="hello"/>
<int-xml:xslt-param name="firstName" expression="headers.fname"/>
</int-xml:xslt-transformer>
如果消息头名称与参数名称一一对应,可以使用xslt-param-headers
属性。在其中,您可以使用通配符进行简单的模式匹配。它支持以下简单的模式样式:xxx*
、xxx
、*xxx
和xxx*yyy
。
您还可以使用<xslt-param/>
元素配置单个XSLT参数。在该元素上,您可以设置expression
属性或value
属性。expression
属性应该是任何有效的SpEL表达式,其中Message
是表达式评估上下文的根对象。value
属性(与Spring bean中的任何value
一样)允许您指定简单的标量值。您还可以使用属性占位符(例如${some.value}
)。因此,使用expression
和value
属性,您可以将XSLT参数映射到Message
的任何可访问部分以及任何文字值。
从 Spring Integration 3.0 开始,您可以通过设置 `transformer-factory-class` 属性来指定转换器工厂类名。
命名空间配置和结果转换器
我们在 使用 `ResultTransformer` 实现 中介绍了使用结果转换器。本节中的示例使用 XML 命名空间配置来说明几个特殊用例。首先,我们定义 `ResultTransformer`,如下例所示
<beans:bean id="resultToDoc" class="o.s.i.xml.transformer.ResultToDocumentTransformer"/>
此 `ResultTransformer` 接受 `StringResult` 或 `DOMResult` 作为输入,并将输入转换为 `Document`。
现在我们可以声明转换器,如下所示
<int-xml:xslt-transformer input-channel="in" output-channel="fahrenheitChannel"
xsl-resource="classpath:noop.xslt" result-transformer="resultToDoc"/>
如果传入消息的有效负载类型为 `Source`,则第一步是使用 `ResultFactory` 确定 `Result`。由于我们没有指定 `ResultFactory`,因此使用默认的 `DomResultFactory`,这意味着转换将生成 `DomResult`。
但是,由于我们指定了 `ResultTransformer`,因此它将被使用,并且生成的 `Message` 有效负载类型为 `Document`。
指定的 `ResultTransformer` 将被 `String` 或 `Document` 有效负载忽略。如果传入消息的有效负载类型为 `String`,则 XSLT 转换后的有效负载为 `String`。类似地,如果传入消息的有效负载类型为 `Document`,则 XSLT 转换后的有效负载为 `Document`。 |
如果消息有效负载不是 `Source`、`String` 或 `Document`,则作为后备选项,我们将尝试使用默认的 `SourceFactory` 创建 `Source`。由于我们没有使用 `source-factory` 属性显式指定 `SourceFactory`,因此使用默认的 `DomSourceFactory`。如果成功,则执行 XSLT 转换,就像有效负载类型为 `Source` 一样,如前几段所述。
`DomSourceFactory` 支持从 `Document`、`File` 或 `String` 有效负载创建 `DOMSource`。 |
下一个转换器声明添加了一个result-type
属性,该属性使用StringResult
作为其值。result-type
在内部由StringResultFactory
表示。因此,您也可以通过使用result-factory
属性添加对StringResultFactory
的引用,这将是相同的。以下示例显示了该转换器声明
<int-xml:xslt-transformer input-channel="in" output-channel="fahrenheitChannel"
xsl-resource="classpath:noop.xslt" result-transformer="resultToDoc"
result-type="StringResult"/>
因为我们使用的是ResultFactory
,所以XsltPayloadTransformer
类的alwaysUseResultFactory
属性被隐式设置为true
。因此,将使用引用的ResultToDocumentTransformer
。
因此,如果您转换类型为String
的有效负载,则结果有效负载的类型为Document
。
[[xsltpayloadtransformer-and-<xsl:output-method=-text-/>]] === XsltPayloadTransformer
和 <xsl:output method="text"/>
<xsl:output method="text"/>
告诉 XSLT 模板从输入源生成纯文本内容。在这种情况下,我们没有理由使用DomResult
。因此,XsltPayloadTransformer
在以下情况下默认使用StringResult
:如果底层javax.xml.transform.Transformer
的method
输出属性返回text
。这种强制转换独立于入站有效负载类型执行。此行为仅在您设置<int-xml:xslt-transformer>
组件的result-type
属性或result-factory
属性时才可用。