如需使用最新稳定版本,请使用 Spring Integration 7.0.4spring-doc.cadn.net.cn

转换 XML 负载

本节介绍如何转换 XML 负载spring-doc.cadn.net.cn

配置转换器为 Bean

本节将解释以下转换器的运作方式,并说明如何将其配置为 Bean:spring-doc.cadn.net.cn

所有 XML 转换器都扩展自 AbstractTransformerAbstractPayloadTransformer,因此实现了 Transformer。 在 Spring Integration 中将 XML 转换器配置为 Bean 时,通常会将 TransformerMessageTransformingHandler 一起配置。 这使得转换器可以作为端点使用。 最后,我们讨论命名空间支持,它允许将转换器配置为 XML 中的元素。spring-doc.cadn.net.cn

反序列化转换器

一个 UnmarshallingTransformer 允许使用 Spring OXM Unmarshaller 的实现来反序列化 XML Source。 Spring 的对象/XML 映射支持提供了多种实现,这些实现支持通过 JAXBCastorJiBX 等进行编组和解组。 反序列化器需要一个 Source 的实例。 如果消息负载不是 Source 的实例,仍会尝试进行转换。 目前支持 StringFilebyte[]org.w3c.dom.Document 类型的负载。 若要创建自定义转换以转换为 Source,可以注入 SourceFactory 的一个实现。spring-doc.cadn.net.cn

如果您没有显式设置 SourceFactory,则 UnmarshallingTransformer 上的属性默认会被设置为 DomSourceFactory

从 5.0 版本开始,UnmarshallingTransformer 还支持将 org.springframework.ws.mime.MimeMessage 作为传入的有效负载。 当通过 SOAP 接收带有 MTOM 附件的原始 WebServiceMessage 时,这非常有用。 有关更多信息,请参阅 MTOM 支持spring-doc.cadn.net.cn

以下示例展示了如何定义一个反序列化转换器:spring-doc.cadn.net.cn

<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。 以下示例配置了一个转换为文档的编组转换器:spring-doc.cadn.net.cn

<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实现时,负载是进行编组的适当源对象。spring-doc.cadn.net.cn

XsltPayloadTransformer

The XsltPayloadTransformer通过使用可扩展样式表语言转换(XSLT)来转换XML负载。 transformer的构造函数需要传入一个ResourceTemplates实例。 传入Templates实例允许对用于创建模板实例的TransformerFactory进行更详细的配置。spring-doc.cadn.net.cn

UnmarshallingTransformer 类似,XsltPayloadTransformer 会对 Source 的实例执行实际的 XSLT 转换。 因此,如果消息负载不是 Source 的实例,仍会尝试进行转换。 StringDocument 类型的负载可直接支持。spring-doc.cadn.net.cn

要创建转换为 Source 的自定义转换器,您可以注入一个 SourceFactory 的实现。spring-doc.cadn.net.cn

如果未显式设置 SourceFactory,则 XsltPayloadTransformer 上的属性默认设置为 DomSourceFactory

默认情况下,XsltPayloadTransformer会创建一个带有Result负载的消息,类似于XmlPayloadMarshallingTransformer。 您可以通过提供ResultFactoryResultTransformer来自定义此行为。spring-doc.cadn.net.cn

以下示例配置了一个可作为 XSLT 负载转换器的 Bean:spring-doc.cadn.net.cn

<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 属性来实现这一点。spring-doc.cadn.net.cn

使用ResultTransformer实现

Both the MarshallingTransformer and the XsltPayloadTransformer let you specify a ResultTransformer. Thus, if the marshalling or XSLT transformation returns a Result, you have the option to also use a ResultTransformer to transform the Result into another format. Spring Integration provides two concrete ResultTransformer implementations:spring-doc.cadn.net.cn

默认情况下,MarshallingTransformer 始终返回一个 Result。 通过指定 ResultTransformer,您可以自定义返回的负载类型。spring-doc.cadn.net.cn

对于 XsltPayloadTransformer,其行为稍微复杂一些。 默认情况下,如果输入负载是 String 的实例或 Document,则 resultTransformer 属性将被忽略。spring-doc.cadn.net.cn

然而,如果输入负载是 Source 或任何其他类型,则应用 resultTransformer 属性。 此外,您可以将 alwaysUseResultFactory 属性设置为 true,这也会导致使用指定的 resultTransformerspring-doc.cadn.net.cn

有关更多信息和示例,请参阅 命名空间配置和结果转换器spring-doc.cadn.net.cn

XML 转换器的命名空间支持

Spring Integration XML 命名空间为所有 XML 转换器提供了命名空间支持,其模板此前已展示。 该命名空间支持根据所提供输入通道的类型,创建EventDrivenConsumerPollingConsumer的实例。 该命名空间支持旨在通过允许使用单个元素创建端点和转换器,来减少 XML 配置的量。spring-doc.cadn.net.cn

使用UnmarshallingTransformer

下面展示了 UnmarshallingTransformer 的命名空间支持。 由于该命名空间会创建一个端点实例而不是转换器,因此您可以在元素内嵌套一个轮询器来控制输入通道的轮询。 以下示例展示了如何实现:spring-doc.cadn.net.cn

<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属性来控制所创建结果的类型。 有效值为StringResultDomResult(默认值)。 以下示例配置了一个编组转换器:spring-doc.cadn.net.cn

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

当提供的结果类型不足以满足需求时,您可以使用result-factory属性来引用自定义的ResultFactory实现,以此替代设置result-type属性。
result-typeresult-factory属性是互斥的。spring-doc.cadn.net.cn

在内部,StringResultDomResult结果类型分别由ResultFactory实现表示:StringResultFactoryDomResultFactory

使用XsltPayloadTransformer

命名空间支持允许您传入一个 XsltPayloadTransformer(用于创建 Templates 实例),或者传入一个预创建的 Templates 实例作为引用。 与编组转换器类似,您可以通过指定 result-factoryresult-type 属性来控制结果输出的类型。 当需要在发送前转换结果时,您可以使用 result-transformer 属性来引用 ResultTransformer 的实现。spring-doc.cadn.net.cn

如果您指定了 result-factoryresult-type 属性,则底层 XsltPayloadTransformeralwaysUseResultFactory 属性将由 XsltPayloadTransformerParser 设置为 true

以下示例配置了两个 XSLT 转换器:spring-doc.cadn.net.cn

<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 提供了两种便捷的方式来实现此目的,如下例所示:spring-doc.cadn.net.cn

<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*yyyspring-doc.cadn.net.cn

您还可以通过使用 <xslt-param/> 元素来配置单独的 XSLT 参数。 在该元素上,您可以设置 expression 属性或 value 属性。 expression 属性应为任何有效的 SpEL 表达式,其中 Message 是表达式求值上下文的根对象。 value 属性(与 Spring bean 中的任何 value 一样)允许您指定简单的标量值。 您还可以使用属性占位符(例如 ${some.value})。 因此,通过 expressionvalue 属性,您可以将 XSLT 参数映射到 Message 的任何可访问部分以及任何字面量值。spring-doc.cadn.net.cn

从 Spring Integration 3.0 开始,您可以通过设置 transformer-factory-class 属性来指定转换器工厂类名。spring-doc.cadn.net.cn

命名空间配置和结果转换器

我们介绍了在 使用ResultTransformer实现中如何使用结果转换器。 本节中的示例使用 XML 命名空间配置来说明几个特殊用例。 首先,我们定义 ResultTransformer,如下例所示:spring-doc.cadn.net.cn

<beans:bean id="resultToDoc" class="o.s.i.xml.transformer.ResultToDocumentTransformer"/>

ResultTransformer 接受 StringResultDOMResult 作为输入,并将输入转换为 Documentspring-doc.cadn.net.cn

现在我们可以声明转换器,如下所示:spring-doc.cadn.net.cn

<int-xml:xslt-transformer input-channel="in" output-channel="fahrenheitChannel"
    xsl-resource="classpath:noop.xslt" result-transformer="resultToDoc"/>

如果传入消息的负载类型为 Source,那么作为第一步,将通过使用 ResultFactory 来确定 Result。 由于我们未指定 ResultFactory,因此将使用默认的 DomResultFactory,这意味着转换结果将生成一个 DomResultspring-doc.cadn.net.cn

然而,由于我们指定了 ResultTransformer,它被使用,生成的 Message 负载类型为 Documentspring-doc.cadn.net.cn

指定的 ResultTransformerStringDocument 负载下将被忽略。 如果传入消息的负载类型为 String,则经过 XSLT 转换后的负载为 String。 同样地,如果传入消息的负载类型为 Document,则经过 XSLT 转换后的负载为 Document。

如果消息负载不是 SourceStringDocument,作为回退选项,我们将尝试使用默认的 SourceFactory 来创建 `Source`。 由于我们未通过 source-factory 属性显式指定 SourceFactory,因此使用了默认的 DomSourceFactory。 如果成功,XSLT 转换将如同消息负载为 Source 类型一样执行,如前文所述。spring-doc.cadn.net.cn

The DomSourceFactory supports the creation of a DOMSource from a Document, a File, or a String payload.

下一个转换器声明添加了一个result-type属性,其值为StringResultresult-type在内部由StringResultFactory表示。 因此,您也可以通过使用result-factory属性来添加对StringResultFactory的引用,结果是一样的。 以下示例展示了该转换器声明:spring-doc.cadn.net.cn

<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 将被使用。spring-doc.cadn.net.cn

因此,如果您将类型为 String 的负载进行转换,生成的负载类型将为 Documentspring-doc.cadn.net.cn

[[xsltpayloadtransformer-and-<xsl:output-method=-text-/>]] === XsltPayloadTransformer and <xsl:output method="text"/>spring-doc.cadn.net.cn

<xsl:output method="text"/> 告诉 XSLT 模板仅从输入源生成文本内容。 在这种情况下,我们没有理由使用 DomResult。 因此,如果底层 javax.xml.transform.Transformer 上名为 method输出属性 返回 text,则 XsltPayloadTransformer 默认为 StringResult。 此强制转换独立于入站负载类型执行。 只有当为 <int-xml:xslt-transformer> 组件设置 result-type 属性或 result-factory 属性时,才可使用此行为。spring-doc.cadn.net.cn