转换 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
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 转换器的命名空间支持
所有 XML 转换器的命名空间支持都在 Spring Integration 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-factory
属性设置result-type
属性的替代方法。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
。
对于String 或Document 有效负载,指定的ResultTransformer 将被忽略。如果传入消息的有效负载类型为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
。因此,如果底层javax.xml.transform.Transformer
的称为method
的输出属性返回text
,则XsltPayloadTransformer
默认为StringResult
。此强制转换独立于入站有效负载类型执行。此行为仅在您设置<int-xml:xslt-transformer>
组件的result-type
属性或result-factory
属性时才可用。