XML 支持 - 处理 XML 有效负载

XML 支持 - 处理 XML 有效负载

Spring Integration 的 XML 支持通过以下组件扩展了 Spring Integration 的核心:spring-doc.cadn.net.cn

您需要将此依赖项包含在您的项目中:spring-doc.cadn.net.cn

专家
<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-xml</artifactId>
    <version>6.0.9</version>
</dependency>
Gradle
compile "org.springframework.integration:spring-integration-xml:6.0.9"

这些组件使在 Spring Integration 中处理 XML 消息变得更加简单。 消息传递组件使用以一系列格式表示的 XML,包括java.lang.String,org.w3c.dom.Documentjavax.xml.transform.Source. 但是,如果需要 DOM 表示(例如,为了计算 XPath 表达式),则String有效负载被转换为所需的类型,然后转换回String. 需要DocumentBuilder如果您未提供命名空间感知实例,请创建一个命名空间感知实例。 当需要更好地控制文档创建时,可以提供适当配置的DocumentBuilder.spring-doc.cadn.net.cn

命名空间支持

Spring Integration XML 模块中的所有组件都提供命名空间支持。 为了启用命名空间支持,您需要导入 Spring Integration XML 模块的模式。 以下示例显示了典型的设置: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:int="http://www.springframework.org/schema/integration"
  xmlns:int-xml="http://www.springframework.org/schema/integration/xml"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    https://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/integration
    https://www.springframework.org/schema/integration/spring-integration.xsd
    http://www.springframework.org/schema/integration/xml
    https://www.springframework.org/schema/integration/xml/spring-integration-xml.xsd">
</beans>

XPath 表达式

Spring Integration XML 模块中的许多组件都与 XPath 表达式一起使用。 这些组件中的每一个都引用已定义为顶级元素的 XPath 表达式,或者使用嵌套的<xpath-expression/>元素。spring-doc.cadn.net.cn

所有形式的 XPath 表达式都会导致创建XPathExpression使用 Springorg.springframework.xml.xpath.XPathExpressionFactory. 创建 XPath 表达式时,将使用类路径上可用的最佳 XPath 实现(JAXP 1.3+ 或 Jaxen,首选 JAXP)。spring-doc.cadn.net.cn

在内部,Spring Integration 使用 Spring Web Services 项目 (https://www.spring.io/spring-ws) 提供的 XPath 功能。 具体来说,我们使用 Spring Web Services XML 模块 (spring-xml-x.x.x.jar)。 要更深入地理解,请参阅 https://docs.spring.io/spring-ws/docs/current/reference/#xpath 中的相应文档。

以下是xpath-expression元素: 以下列表显示了xpath-expression元素:spring-doc.cadn.net.cn

<int-xml:xpath-expression expression="" (1)
          id=""                         (2)
          namespace-map=""              (3)
          ns-prefix=""                  (4)
          ns-uri="">                    (5)
    <map></map>                         (6)
</int-xml:xpath-expression>
1 定义 XPath 表达式。 必填。
2 基础 Bean 定义的标识符。 它是org.springframework.xml.xpath.XPathExpression. 自选。
3 对包含命名空间的映射的引用。 映射的键定义命名空间前缀,映射的值设置命名空间 URI。 同时指定此属性和map元素或ns-prefixns-uri属性。 自选。
4 允许您将命名空间前缀直接设置为 XPath 表达式元素上的属性。 如果您将ns-prefix,您还必须将ns-uri属性。 自选。
5 允许您直接将命名空间 URI 设置为 XPath 表达式元素上的属性。 如果您将ns-uri,您还必须将ns-prefix属性。 自选。
6 定义包含命名空间的映射。 只有一个mapchild 元素。 映射的键定义命名空间前缀,映射的值设置命名空间 URI。 同时指定此元素和map属性或将ns-prefixns-uri属性。 自选。
为 XPath 表达式提供命名空间(可选)

对于 XPath 表达式元素,您可以提供命名空间信息作为配置参数。 可以使用以下选项之一来定义命名空间:spring-doc.cadn.net.cn

所有三个选项都是相互排斥的。 只能设置一个选项。spring-doc.cadn.net.cn

以下示例显示了使用 XPath 表达式的几种不同方法,包括前面提到的用于设置 XML 命名空间的选项:spring-doc.cadn.net.cn

<int-xml:xpath-filter id="filterReferencingXPathExpression"
                      xpath-expression-ref="refToXpathExpression"/>

<int-xml:xpath-expression id="refToXpathExpression" expression="/name"/>

<int-xml:xpath-filter id="filterWithoutNamespace">
    <int-xml:xpath-expression expression="/name"/>
</int-xml:xpath-filter>

<int-xml:xpath-filter id="filterWithOneNamespace">
    <int-xml:xpath-expression expression="/ns1:name"
                              ns-prefix="ns1" ns-uri="www.example.org"/>
</int-xml:xpath-filter>

<int-xml:xpath-filter id="filterWithTwoNamespaces">
    <int-xml:xpath-expression expression="/ns1:name/ns2:type">
        <map>
            <entry key="ns1" value="www.example.org/one"/>
            <entry key="ns2" value="www.example.org/two"/>
        </map>
    </int-xml:xpath-expression>
</int-xml:xpath-filter>

<int-xml:xpath-filter id="filterWithNamespaceMapReference">
    <int-xml:xpath-expression expression="/ns1:name/ns2:type"
                              namespace-map="defaultNamespaces"/>
</int-xml:xpath-filter>

<util:map id="defaultNamespaces">
    <util:entry key="ns1" value="www.example.org/one"/>
    <util:entry key="ns2" value="www.example.org/two"/>
</util:map>
将 XPath 表达式与默认命名空间结合使用

使用默认命名空间时,您可能会遇到行为与预期不同的情况。 假设我们有以下 XML 文档(代表两本书的订单):spring-doc.cadn.net.cn

<?xml version="1.0" encoding="UTF-8"?>
<order>
    <orderItem>
        <isbn>0321200683</isbn>
        <quantity>2</quantity>
    </orderItem>
    <orderItem>
        <isbn>1590596439</isbn>
        <quantity>1</quantity>
    </orderItem>
</order>

本文档不声明命名空间。 因此,应用以下 XPath 表达式按预期工作:spring-doc.cadn.net.cn

<int-xml:xpath-expression expression="/order/orderItem" />

您可能期望相同的表达式也适用于以下 XML 文件:spring-doc.cadn.net.cn

<?xml version="1.0" encoding="UTF-8"?>
<order xmlns="http://www.example.org/orders">
	<orderItem>
		<isbn>0321200683</isbn>
		<quantity>2</quantity>
	</orderItem>
	<orderItem>
		<isbn>1590596439</isbn>
		<quantity>1</quantity>
	</orderItem>
</order>

前面的示例看起来与前面的示例完全相同,但声明了一个默认命名空间。spring-doc.cadn.net.cn

但是,前面的 XPath 表达式 (/order/orderItem) 在这种情况下失败。spring-doc.cadn.net.cn

为了解决此问题,您必须通过设置ns-prefixns-uri属性或通过设置namespace-map属性。 命名空间 URI 必须与 XML 文档中声明的命名空间匹配。 在前面的示例中,即http://www.example.org/orders.spring-doc.cadn.net.cn

但是,您可以任意选择命名空间前缀。事实上,提供空字符串实际上有效。(但是,不允许使用 null。)对于由空字符串组成的命名空间前缀,则 Xpath 表达式必须使用冒号 (“:”) 来指示默认命名空间。如果省略冒号,则 XPath 表达式不匹配。以下 XPath 表达式与前面示例中的 XML 文档匹配:spring-doc.cadn.net.cn

<int-xml:xpath-expression expression="/:order/:orderItem"
    ns-prefix="" ns-uri="https://www.example.org/prodcuts"/>

您还可以提供任何其他任意选择的命名空间前缀。以下 XPath 表达式(使用myorder命名空间前缀)也匹配:spring-doc.cadn.net.cn

<int-xml:xpath-expression expression="/myorder:order/myorder:orderItem"
    ns-prefix="myorder" ns-uri="https://www.example.org/prodcuts"/>

命名空间 URI 是真正重要的信息,而不是前缀。Jaxen 很好地总结了这一点:spring-doc.cadn.net.cn

在 XPath 1.0 中,所有未带前缀的名称都是不限定的。不要求 XPath 表达式中使用的前缀与正在查询的文档中使用的前缀相同。只需要匹配命名空间 URI,而不是前缀。

转换 XML 有效负载

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

将 Transformer 配置为 Bean

本节将解释以下 transformer 的工作原理以及如何将它们配置为 bean:spring-doc.cadn.net.cn

所有 XML 转换器都扩展了AbstractTransformerAbstractPayloadTransformer因此实施Transformer. 在 Spring Integration 中将 XML 转换器配置为 bean 时,您通常会配置Transformer结合MessageTransformingHandler. 这允许将转换器用作端点。 最后,我们讨论命名空间支持,它允许将转换器配置为 XML 中的元素。spring-doc.cadn.net.cn

UnmarshallingTransformer

UnmarshallingTransformer让 XMLSource通过使用 Spring OXM 的实现进行解组 Unmarshaller. Spring 的 Object/XML Mapping 支持提供了多种实现,这些实现支持使用 JAXBCastorJiBX 等进行编组和解编。 unmarshaller 需要一个Source. 如果消息有效负载不是Source,仍在尝试转换。 现在String,File,byte[]org.w3c.dom.Document支持有效负载。 要创建自定义转换为Source,您可以注入一个SourceFactory.spring-doc.cadn.net.cn

如果您没有显式设置SourceFactory,则UnmarshallingTransformer默认情况下,设置为DomSourceFactory.

从 5.0 版开始,UnmarshallingTransformer还支持org.springframework.ws.mime.MimeMessage作为传入的有效负载。当我们收到原始WebServiceMessage通过 SOAP 使用 MTOM 附件。有关更多信息,请参阅 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

MarshallingTransformer允许使用 Spring OXM 将对象图转换为 XMLMarshaller. 默认情况下,MarshallingTransformer返回一个DomResult. 但是,您可以通过配置替代项来控制结果的类型ResultFactoryStringResultFactory. 在许多情况下,将有效负载转换为替代 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将 payload 对象传递给Marshaller. 但是,如果其布尔值extractPayload属性设置为false,整个Message实例被传递给Marshaller相反。 这对于Marshaller接口,但通常,有效负载是用于封送的适当源对象,当您委托给各种Marshaller实现。spring-doc.cadn.net.cn

XsltPayloadTransformer

XsltPayloadTransformer使用可扩展样式表语言转换 (XSLT) 转换 XML 有效负载。转换器的构造函数需要传入 ResourceTemplates 的实例。传入Templates实例允许对TransformerFactory用于创建模板实例。spring-doc.cadn.net.cn

UnmarshallingTransformerXsltPayloadTransformerSource. 因此,如果消息有效负载不是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实现

两个MarshallingTransformerXsltPayloadTransformer允许您指定一个ResultTransformer. 因此,如果封送处理或 XSLT 转换返回Result,您还可以选择使用ResultTransformerResult转换为另一种格式。 Spring Integration 提供了两个具体的ResultTransformer实现:spring-doc.cadn.net.cn

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

对于XsltPayloadTransformer. 默认情况下,如果输入有效负载是StringDocumentresultTransformer属性被忽略。spring-doc.cadn.net.cn

但是,如果输入有效负载是Source或任何其他类型,resultTransformer属性。此外,您可以将alwaysUseResultFactory属性设置为true,这也会导致指定的resultTransformer待使用。spring-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-channeloutput-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"/>

如果提供的结果类型不够,则可以提供对ResultFactory作为将result-type属性,使用result-factory属性。 这result-typeresult-factory属性是互斥的。spring-doc.cadn.net.cn

在内部,StringResultDomResult结果类型由ResultFactory实现:StringResultFactoryDomResultFactory分别。
使用XsltPayloadTransformer

命名空间支持XsltPayloadTransformer让您传入Resource(为了创建Templatesinstance)或传入预先创建的Templates实例作为参考。 与封送转换器一样,可以通过指定result-factoryresult-type属性。 当您需要在发送前转换结果时,您可以使用result-transformer属性来引用ResultTransformer.spring-doc.cadn.net.cn

如果指定result-factoryresult-type属性,则alwaysUseResultFactory基础上的属性XsltPayloadTransformer设置为true通过XsltPayloadTransformerParser.

以下示例配置两个 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,*xxxxxx*yyy.spring-doc.cadn.net.cn

您还可以使用<xslt-param/>元素。 在该元素上,您可以将expression属性或value属性。 这expression属性应该是任何有效的 SpEL 表达式,其中Message作为表达式求值上下文的根对象。 这value属性(与任何value在 Spring bean 中)允许您指定简单的标量值。 您还可以使用属性占位符(例如${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作为输入,并将输入转换为Document.spring-doc.cadn.net.cn

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

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

如果传入邮件的有效负载类型为Source,然后,作为第一步,Result通过使用ResultFactory. 由于我们没有指定ResultFactory,默认值DomResultFactory,这意味着转换会产生DomResult.spring-doc.cadn.net.cn

但是,正如我们指定的那样ResultTransformer,它被使用并得到Message有效负载的类型为Document.spring-doc.cadn.net.cn

指定的ResultTransformer被忽略StringDocument负载。 如果传入邮件的有效负载类型为String,则 XSLT 转换后的有效负载是String. 同样,如果传入消息的有效负载类型为Document,则 XSLT 转换后的有效负载是 'Document'。

如果消息有效负载不是Source一个StringDocument,作为后备选项,我们尝试使用默认的SourceFactory. 由于我们没有指定SourceFactory显式地使用source-factory属性,默认DomSourceFactory被使用。 如果成功,则执行 XSLT 转换,就像有效负载的类型为Source,如前几段所述。spring-doc.cadn.net.cn

DomSourceFactory支持创建DOMSourceDocument一个FileString有效载荷。

下一个 transformer 声明将result-type使用StringResult作为其价值。 这result-type在内部由StringResultFactory. 因此,您还可以添加对StringResultFactory,通过使用result-factory属性,这将是相同的。 以下示例显示了 transformer 声明: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"/>

因为我们使用ResultFactoryalwaysUseResultFactory属性的XsltPayloadTransformerclass 被隐式设置为true. 因此,引用的ResultToDocumentTransformer被使用。spring-doc.cadn.net.cn

因此,如果将类型为String,生成的有效负载类型为Document.spring-doc.cadn.net.cn

XsltPayloadTransformer<xsl:output method="text"/>

<xsl:output method="text"/>告诉 XSLT 模板仅从输入源生成文本内容。在这种特殊情况下,我们没有理由使用DomResult. 因此,XsltPayloadTransformer默认为StringResult如果输出属性调用methodjavax.xml.transform.Transformer返回text. 此强制独立于入站有效负载类型执行。此行为仅适用于您设置的result-type属性或result-factory属性的<int-xml:xslt-transformer>元件。spring-doc.cadn.net.cn

使用 XPath 转换 XML 消息

在消息转换方面,XPath 是转换具有 XML 有效负载的消息的好方法。您可以通过使用<xpath-transformer/>元素。spring-doc.cadn.net.cn

简单的 XPath 转换

考虑以下转换器配置:spring-doc.cadn.net.cn

<int-xml:xpath-transformer input-channel="inputChannel" output-channel="outputChannel"
      xpath-expression="/person/@name" />

还要考虑以下事项Message:spring-doc.cadn.net.cn

Message<?> message =
  MessageBuilder.withPayload("<person name='John Doe' age='42' married='true'/>").build();

将此消息发送到 'inputChannel' 后,之前配置的 XPath 转换器将此 XML 消息转换为简单的Message有效负载为“John Doe”,所有这些都基于xpath-expression属性。spring-doc.cadn.net.cn

XPath 还允许您将提取的元素简单转换为所需类型。有效的返回类型在javax.xml.xpath.XPathConstants并遵循javax.xml.xpath.XPath接口。spring-doc.cadn.net.cn

以下常量由XPathConstants类:BOOLEAN,DOM_OBJECT_MODEL,NODE,NODESET,NUMBERSTRING.spring-doc.cadn.net.cn

您可以使用evaluation-type属性的<xpath-transformer/>元素,如以下示例所示(两次):spring-doc.cadn.net.cn

<int-xml:xpath-transformer input-channel="numberInput" xpath-expression="/person/@age"
                           evaluation-type="NUMBER_RESULT" output-channel="output"/>

<int-xml:xpath-transformer input-channel="booleanInput"
                           xpath-expression="/person/@married = 'true'"
                           evaluation-type="BOOLEAN_RESULT" output-channel="output"/>

节点映射器

如果您需要为 XPath 表达式提取的节点提供自定义映射,则可以提供对org.springframework.xml.xpath.NodeMapper(由XPathOperations映射的实现Node每个节点的对象)。要提供对NodeMapper,您可以使用node-mapper属性,如以下示例所示:spring-doc.cadn.net.cn

<int-xml:xpath-transformer input-channel="nodeMapperInput" xpath-expression="/person/@age"
                           node-mapper="testNodeMapper" output-channel="output"/>

以下示例显示了NodeMapper适用于上述示例的实现:spring-doc.cadn.net.cn

class TestNodeMapper implements NodeMapper {
  public Object mapNode(Node node, int nodeNum) throws DOMException {
    return node.getTextContent() + "-mapped";
  }
}

XML 有效负载转换器

您还可以使用org.springframework.integration.xml.XmlPayloadConverter以提供更精细的转换。以下示例演示如何定义一个:spring-doc.cadn.net.cn

<int-xml:xpath-transformer input-channel="customConverterInput"
                           output-channel="output" xpath-expression="/test/@type"
                           converter="testXmlPayloadConverter" />

以下示例显示了XmlPayloadConverter适用于上述示例的实现:spring-doc.cadn.net.cn

class TestXmlPayloadConverter implements XmlPayloadConverter {
  public Source convertToSource(Object object) {
    throw new UnsupportedOperationException();
  }
  //
  public Node convertToNode(Object object) {
    try {
      return DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(
          new InputSource(new StringReader("<test type='custom'/>")));
    }
    catch (Exception e) {
      throw new IllegalStateException(e);
    }
  }
  //
  public Document convertToDocument(Object object) {
    throw new UnsupportedOperationException();
  }
}

如果您不提供此参考,则DefaultXmlPayloadConverter被使用。 在大多数情况下,它应该足够了,因为它可以从Node,Document,Source,File,String,InputStreambyte[]负载。 如果您需要扩展到该默认实现的功能之外,则上游Transformer可能比在此处提供对此策略的自定义实现的引用更好的选择。spring-doc.cadn.net.cn

拆分 XML 消息

XPathMessageSplitter支持具有StringDocument负载。 拆分器使用提供的 XPath 表达式将有效负载拆分为多个节点。 默认情况下,这会导致每个Node实例成为新消息的有效负载。 当每条消息应为Document,您可以将createDocuments旗。 其中String有效负载被传入,有效负载被转换,然后拆分,然后转换回许多String消息。 XPath 拆分器实现MessageHandler因此,应与适当的端点一起配置(有关更简单的配置替代方案,请参阅以下示例之后的命名空间支持示例)。 以下示例配置了一个使用XPathMessageSplitter:spring-doc.cadn.net.cn

<bean id="splittingEndpoint"
      class="org.springframework.integration.endpoint.EventDrivenConsumer">
    <constructor-arg ref="orderChannel" />
    <constructor-arg>
        <bean class="org.springframework.integration.xml.splitter.XPathMessageSplitter">
            <constructor-arg value="/order/items" />
            <property name="documentBuilder" ref="customisedDocumentBuilder" />
            <property name="outputChannel" ref="orderItemsChannel" />
        </bean>
    </constructor-arg>
</bean>

XPath 拆分器命名空间支持允许您创建具有输入通道和输出通道的消息端点,如以下示例所示:spring-doc.cadn.net.cn

<!-- Split the order into items and create a new message for each item node -->
<int-xml:xpath-splitter id="orderItemSplitter"
                       input-channel="orderChannel"
                       output-channel="orderItemsChannel">
    <int-xml:xpath-expression expression="/order/items"/>
</int-xml:xpath-splitter>

<!-- Split the order into items, create a new document for each item-->
<int-xml:xpath-splitter id="orderItemDocumentSplitter"
                       input-channel="orderChannel"
                       output-channel="orderItemsChannel"
                       create-documents="true">
    <int-xml:xpath-expression expression="/order/items"/>
    <int:poller fixed-rate="2000"/>
</int-xml:xpath-splitter>

从 4.2 版开始,XPathMessageSplitter公开outputProperties(例如OutputKeys.OMIT_XML_DECLARATION) 属性的javax.xml.transform.Transformer实例,当请求payload不是类型org.w3c.dom.Node. 以下示例定义了一个属性,并将其与output-properties财产:spring-doc.cadn.net.cn

<util:properties id="outputProperties">
	<beans:prop key="#{T (javax.xml.transform.OutputKeys).OMIT_XML_DECLARATION}">yes</beans:prop>
</util:properties>

<xpath-splitter input-channel="input"
             output-properties="outputProperties">
    <xpath-expression expression="/orders/order"/>
</xpath-splitter>

version 4.2XPathMessageSplitter暴露了一个iterator选项作为boolean标志(默认为true). 这允许在下游流中“流式传输”拆分节点。使用iteratormode 设置为true,每个节点在迭代时进行转换。 什么时候false,在拆分节点开始发送到输出通道之前,所有条目都会首先进行转换。(您可以将区别视为“转换、发送、转换、发送”与“转换、转换、发送、发送”。有关更多信息,请参阅拆分器spring-doc.cadn.net.cn

使用 XPath 路由 XML 消息

与基于 SpEL 的路由器类似,Spring Integration 支持基于 XPath 表达式路由消息,这允许您创建具有输入通道但没有输出通道的消息端点。相反,一个或多个输出通道是动态确定的。以下示例显示了如何创建这样的路由器:spring-doc.cadn.net.cn

<int-xml:xpath-router id="orderTypeRouter" input-channel="orderChannel">
    <int-xml:xpath-expression expression="/order/type"/>
</int-xml:xpath-router>
有关路由器之间通用属性的概述,请参阅通用路由器参数

在内部,XPath 表达式被计算为 typeNODESET并转换为List<String>表示通道名称。通常,此类列表包含单个通道名称。但是,根据 XPath 表达式的结果,如果 XPath 表达式返回多个值,则 XPath 路由器也可以采用收件人列表路由器的特征。在这种情况下,List<String>包含多个通道名称。因此,消息将发送到列表中的所有通道。spring-doc.cadn.net.cn

因此,假设传递给以下路由器配置的 XML 文件包含许多responder表示通道名称的子元素,则消息将发送到所有这些通道:spring-doc.cadn.net.cn

<!-- route the order to all responders-->
<int-xml:xpath-router id="responderRouter" input-channel="orderChannel">
    <int-xml:xpath-expression expression="/request/responders"/>
</int-xml:xpath-router>

如果返回值不直接表示通道名称,则可以指定其他映射参数以将这些返回值映射到实际通道名称。例如,如果/request/responders表达式的结果是两个值 (responderAresponderB),但您不想将响应方名称耦合到通道名称,则可以提供其他映射配置,例如:spring-doc.cadn.net.cn

<!-- route the order to all responders-->
<int-xml:xpath-router id="responderRouter" input-channel="orderChannel">
    <int-xml:xpath-expression expression="/request/responders"/>
    <int-xml:mapping value="responderA" channel="channelA"/>
    <int-xml:mapping value="responderB" channel="channelB"/>
</int-xml:xpath-router>

如前所述,XPath 表达式的默认求值类型为NODESET,它被转换为List<String>的通道名称,用于处理单通道方案以及多通道方案。spring-doc.cadn.net.cn

尽管如此,某些 XPath 表达式的计算结果可能为 typeString从一开始。 例如,考虑以下 XPath 表达式:spring-doc.cadn.net.cn

name(./node())

此表达式返回根节点的名称。 如果默认评估类型NODESET,则会导致异常。spring-doc.cadn.net.cn

对于这些方案,您可以使用evaluate-as-string属性,用于管理评估类型。 是的FALSE默认情况下。 但是,如果将其设置为TRUEString使用评估类型。spring-doc.cadn.net.cn

XPath 1.0 指定了 4 种数据类型:spring-doc.cadn.net.cn

当 XPath 路由器使用可选的evaluate-as-string属性,则返回值由string()函数,如 XPath 规范中定义。 这意味着,如果表达式选择多个节点,它将返回第一个节点的字符串值。spring-doc.cadn.net.cn

有关详细信息,请参阅:spring-doc.cadn.net.cn

例如,如果我们想根据根节点的名称进行路由,可以使用以下配置:spring-doc.cadn.net.cn

<int-xml:xpath-router id="xpathRouterAsString"
        input-channel="xpathStringChannel"
        evaluate-as-string="true">
    <int-xml:xpath-expression expression="name(./node())"/>
</int-xml:xpath-router>

XML 有效负载转换器

对于 XPath 路由器,您还可以指定在 XPath 评估之前转换有效负载时要使用的转换器。 因此,XPath 路由器支持XmlPayloadConverter策略,并且在配置xpath-router元素,可以通过converter属性。spring-doc.cadn.net.cn

如果未显式提供此引用,则DefaultXmlPayloadConverter被使用。 在大多数情况下,它应该足够了,因为它可以从 Node、Document、Source、File 和 String 类型的有效负载进行转换。 如果您需要扩展到该默认实现的功能之外,那么在大多数情况下,上游 Transformer 通常是更好的选择,而不是在此处提供对此策略的自定义实现的引用。spring-doc.cadn.net.cn

XPath 标头扩充器

XPath 标头扩充器定义了一个标头扩充器消息转换器,该转换器根据消息有效负载评估 XPath 表达式,并将评估结果插入到消息头中。spring-doc.cadn.net.cn

以下列表显示了所有可用的配置参数:spring-doc.cadn.net.cn

<int-xml:xpath-header-enricher default-overwrite="true"    (1)
                               id=""                       (2)
                               input-channel=""            (3)
                               output-channel=""           (4)
                               should-skip-nulls="true">   (5)
    <int:poller></int:poller>                              (6)
    <int-xml:header name=""                                (7)
                    evaluation-type="STRING_RESULT"        (8)
                    header-type="int"                      (9)
                    overwrite="true"                       (10)
                    xpath-expression=""                    (11)
                    xpath-expression-ref=""/>              (12)
</int-xml:xpath-header-enricher>
1 指定是否覆盖现有标头值的默认布尔值。 它仅对不提供自己的“覆盖”属性的子元素生效。 如果未设置“default- overwrite”属性,则指定的标头值不会覆盖任何具有相同标头名称的现有标头值。 自选。
2 基础 Bean 定义的 ID。 自选。
3 此端点的接收消息通道。 自选。
4 将扩充消息发送到的通道。 自选。
5 指定是否应跳过空值(例如可能从表达式计算中返回的值)。 默认值为true. 如果空值应触发相应标头的删除,请将其设置为false. 自选。
6 与标头扩充器一起使用的轮询器。 自选。
7 要扩充的标头的名称。 命令的。
8 XPath 评估预期的结果类型。 如果您没有设置header-type属性,这是标头值的类型。 允许使用以下值:BOOLEAN_RESULT,STRING_RESULT,NUMBER_RESULT,NODE_RESULTNODE_LIST_RESULT. 如果未设置,则在内部默认为XPathEvaluationType.STRING_RESULT. 自选。
9 标头值类型的完全限定类名。 XPath 评估的结果通过以下方式转换为此类型ConversionService. 例如,这允许NUMBER_RESULT(双精度)转换为Integer. 该类型可以声明为基元(例如int),但结果始终是等效的包装类(例如Integer). 相同的集成ConversionService有效负载类型转换中讨论的用于转换,因此通过向服务添加自定义转换器来支持转换为自定义类型。 自选。
10 布尔值,指示此标头值是否应覆盖相同名称的现有标头值(如果输入上已存在)Message.
11 XPath 表达式作为String. 您必须设置此属性或xpath-expression-ref,但不能两者兼而有之。
12 XPath 表达式引用。 您必须设置此属性或xpath-expression,但不能两者兼而有之。

使用 XPath 过滤器

此组件定义了基于 XPath 的消息过滤器。 在内部,这些组件使用MessageFilter包装AbstractXPathMessageSelector.spring-doc.cadn.net.cn

有关更多详细信息,请参阅过滤器

要使用 XPath 过滤器,您至少必须通过声明xpath-expression元素或通过引用 XPath 表达式xpath-expression-ref属性。spring-doc.cadn.net.cn

如果提供的 XPath 表达式计算结果为boolean值,则不需要进一步的配置参数。 但是,如果 XPath 表达式的计算结果为String,则应将match-value属性,评估结果与之匹配。spring-doc.cadn.net.cn

match-type有三个选项:spring-doc.cadn.net.cn

  • exact:对应于equalsjava.lang.String. 底层实现使用StringValueTestXPathMessageSelectorspring-doc.cadn.net.cn

  • case-insensitive:对应于equals-ignore-casejava.lang.String. 底层实现使用StringValueTestXPathMessageSelectorspring-doc.cadn.net.cn

  • regex:匹配作一java.lang.String. 底层实现使用RegexTestXPathMessageSelectorspring-doc.cadn.net.cn

当提供 'match-type' 值 'regex' 时,与match-value属性必须是有效的正则表达式。spring-doc.cadn.net.cn

以下示例显示了xpath-filter元素:spring-doc.cadn.net.cn

<int-xml:xpath-filter discard-channel=""                      (1)
                      id=""                                   (2)
                      input-channel=""                        (3)
                      match-type="exact"                      (4)
                      match-value=""                          (5)
                      output-channel=""                       (6)
                      throw-exception-on-rejection="false"    (7)
                      xpath-expression-ref="">                (8)
    <int-xml:xpath-expression ... />                          (9)
    <int:poller ... />                                        (10)
</int-xml:xpath-filter>
1 要发送被拒绝邮件的邮件通道。 自选。
2 基础 Bean 定义的 ID。 自选。
3 此端点的接收消息通道。 自选。
4 要在 XPath 评估结果和match-value. 默认值为exact. 自选。
5 要与 XPath 评估结果匹配的字符串值。如果未设置此属性,则 XPath 评估必须生成布尔结果。 自选。
6 将与筛选条件匹配的邮件分派到的通道。 自选。
7 默认情况下,此属性设置为false和被拒绝的邮件(与筛选条件不匹配的邮件)将以静默方式删除。但是,如果设置为true,消息拒绝会导致错误情况,并将异常向上游传播到调用方。 自选。
8 引用要计算的 XPath 表达式实例。
9 此子元素设置要计算的 XPath 表达式。如果不包含此元素,则必须将xpath-expression-ref属性。 此外,您只能包含一个xpath-expression元素。
10 与 XPath 过滤器一起使用的轮询器。 自选。

#xpath SpEL 功能

Spring Integration 从 3.0 版开始,提供了内置的#xpathSpEL 函数,该函数调用XPathUtils.evaluate(…​)static 方法。此方法委托给org.springframework.xml.xpath.XPathExpression. 以下列表显示了一些用法示例:spring-doc.cadn.net.cn

<transformer expression="#xpath(payload, '/name')"/>

<filter expression="#xpath(payload, headers.xpath, 'boolean')"/>

<splitter expression="#xpath(payload, '//book', 'document_list')"/>

<router expression="#xpath(payload, '/person/@age', 'number')">
    <mapping channel="output1" value="16"/>
    <mapping channel="output2" value="45"/>
</router>

#xpath()还支持用于转换 XPath 评估结果的第三个可选参数。它可以是 String 常量 (string,boolean,number,node,node_listdocument_list) 或org.springframework.xml.xpath.NodeMapper实例。 默认情况下,#xpathSpEL 函数返回一个StringXPath 评估的表示形式。spring-doc.cadn.net.cn

要启用#xpathSpEL 函数,您可以添加spring-integration-xml.jar到类路径。您无需声明 Spring Integration XML 命名空间中的任何组件。

有关详细信息,请参阅“'Spring 表达式语言 (SpEL)”。spring-doc.cadn.net.cn

XML 验证过滤器

XML 验证过滤器允许您根据提供的架构实例验证传入消息。支持以下架构类型:spring-doc.cadn.net.cn

验证失败的消息可以静默删除,也可以转发到可定义的discard-channel. 此外,您可以将此过滤器配置为抛出Exception以防验证失败。spring-doc.cadn.net.cn

以下列表显示了所有可用的配置参数:spring-doc.cadn.net.cn

<int-xml:validating-filter discard-channel=""                    (1)
                           id=""                                 (2)
                           input-channel=""                      (3)
                           output-channel=""                     (4)
                           schema-location=""                    (5)
                           schema-type="xml-schema"              (6)
                           throw-exception-on-rejection="false"  (7)
                           xml-converter=""                      (8)
                           xml-validator="">                     (9)
    <int:poller .../>                                            (10)
</int-xml:validating-filter>
1 要发送被拒绝邮件的邮件通道。 自选。
2 基础 Bean 定义的 ID。 自选。
3 此端点的接收消息通道。 自选。
4 要发送已接受消息的消息通道。 自选。
5 设置架构的位置,以验证消息的有效负载。 在内部使用org.springframework.core.io.Resource接口。 您可以设置此属性或xml-validator属性,但不能同时使用两者。 自选。
6 设置架构类型。 可以是xml-schemarelax-ng. 自选。 如果未设置,则默认为xml-schema,在内部翻译为org.springframework.xml.validation.XmlValidatorFactory#SCHEMA_W3C_XML.
7 如果true一个MessageRejectedException如果对提供的消息的有效负载进行验证失败,则会引发。 默认为false如果未设置。 自选。
8 对自定义的引用org.springframework.integration.xml.XmlPayloadConverter策略。 自选。
9 对自定义的引用sorg.springframework.xml.validation.XmlValidator策略。 您可以设置此属性或schema-location属性,但不能同时使用两者。 自选。
10 与 XPath 过滤器一起使用的轮询器。 自选。