跳到主要内容
版本:7.0.2

使用 XPath 路由 XML 消息

DeepSeek V3 中英对照 Routing XML Messages with XPath

与基于SpEL的路由器类似,Spring Integration提供了基于XPath表达式的消息路由支持,允许您创建一个具有输入通道但无输出通道的消息端点。相反,一个或多个输出通道会被动态确定。以下示例展示了如何创建这样的路由器:

<int-xml:xpath-router id="orderTypeRouter" input-channel="orderChannel">
<int-xml:xpath-expression expression="/order/type"/>
</int-xml:xpath-router>
备注

有关路由器通用属性的概述,请参阅通用路由器参数

在内部,XPath 表达式会被评估为 NODESET 类型,并转换为代表通道名称的 List<String>。通常,这样的列表包含单个通道名称。然而,根据 XPath 表达式的结果,如果 XPath 表达式返回多个值,XPath 路由器也可以具备接收者列表路由器的特性。在这种情况下,List<String> 包含多个通道名称。因此,消息会被发送到列表中的所有通道。

因此,假设传递给以下路由器配置的 XML 文件包含许多代表通道名称的 responder 子元素,消息将被发送到所有这些通道:

<!-- 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),但你不想将响应者名称与通道名称直接关联,你可以提供额外的映射配置,如下所示:

<!-- 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>,这既能处理单通道场景,也能处理多通道场景。

尽管如此,某些XPath表达式从一开始就可能被评估为String类型。例如,考虑以下XPath表达式:

name(./node())

该表达式返回根节点的名称。如果使用默认的求值类型 NODESET,则会导致异常。

对于这些场景,你可以使用 evaluate-as-string 属性,它允许你管理评估类型。该属性默认为 FALSE。但是,如果你将其设置为 TRUE,则会使用 String 评估类型。

备注

XPath 1.0 规定了 4 种数据类型:

  • 节点集
  • 字符串
  • 数字
  • 布尔值

当 XPath 路由器使用可选的 evaluate-as-string 属性来评估表达式时,返回值由 XPath 规范中定义的 string() 函数决定。这意味着如果表达式选择了多个节点,它将返回第一个节点的字符串值。

更多信息,请参阅:

例如,如果我们希望根据根节点的名称进行路由,可以使用以下配置:

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

开箱即用的 #xpath() SpEL 函数 功能强大,足以与通用路由器定义(包括收件人列表路由器)配合使用:

<int:recipient-list-router input-channel="xpathRecipientsInput">
<int:recipient channel="channelA" selector-expression="#xpath(payload, '/passenger/age/text() &lt;= 2', 'boolean')"/>
<int:recipient channel="channelB" selector-expression="#xpath(payload, '/passenger/age/text() > 12', 'boolean')"/>
</int:recipient-list-router>

XML 负载转换器

对于XPath路由器,您还可以指定在XPath评估前转换负载时使用的转换器。因此,XPath路由器支持XmlPayloadConverter策略的自定义实现,并且在XML中配置xpath-router元素时,可以通过converter属性引用此类实现。

如果未明确提供此引用,将使用 DefaultXmlPayloadConverter。在大多数情况下,它应该足够使用,因为它能够转换 Node、Document、Source、File 和 String 类型的负载。如果你需要扩展超出该默认实现的能力,那么在大多数情况下,通常更好的选择是使用上游 Transformer,而不是在此处提供对此策略的自定义实现的引用。