XML 支持 - 处理 XML 有效负载
XML 支持 - 处理 XML 有效负载
Spring Integration 的 XML 支持通过以下组件扩展了 Spring Integration 的核心:
您需要将此依赖项包含在您的项目中:
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-xml</artifactId>
<version>6.0.9</version>
</dependency>
compile "org.springframework.integration:spring-integration-xml:6.0.9"
这些组件使在 Spring Integration 中处理 XML 消息变得更加简单。
消息传递组件使用以一系列格式表示的 XML,包括java.lang.String
,org.w3c.dom.Document
和javax.xml.transform.Source
.
但是,如果需要 DOM 表示(例如,为了计算 XPath 表达式),则String
有效负载被转换为所需的类型,然后转换回String
.
需要DocumentBuilder
如果您未提供命名空间感知实例,请创建一个命名空间感知实例。
当需要更好地控制文档创建时,可以提供适当配置的DocumentBuilder
.
命名空间支持
Spring Integration XML 模块中的所有组件都提供命名空间支持。 为了启用命名空间支持,您需要导入 Spring Integration XML 模块的模式。 以下示例显示了典型的设置:
<?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/>
元素。
所有形式的 XPath 表达式都会导致创建XPathExpression
使用 Springorg.springframework.xml.xpath.XPathExpressionFactory
.
创建 XPath 表达式时,将使用类路径上可用的最佳 XPath 实现(JAXP 1.3+ 或 Jaxen,首选 JAXP)。
在内部,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
元素:
<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-prefix 和ns-uri 属性。
自选。 |
4 | 允许您将命名空间前缀直接设置为 XPath 表达式元素上的属性。
如果您将ns-prefix ,您还必须将ns-uri 属性。
自选。 |
5 | 允许您直接将命名空间 URI 设置为 XPath 表达式元素上的属性。
如果您将ns-uri ,您还必须将ns-prefix 属性。
自选。 |
6 | 定义包含命名空间的映射。
只有一个map child 元素。
映射的键定义命名空间前缀,映射的值设置命名空间 URI。
同时指定此元素和map 属性或将ns-prefix 和ns-uri 属性。
自选。 |
为 XPath 表达式提供命名空间(可选)
对于 XPath 表达式元素,您可以提供命名空间信息作为配置参数。 可以使用以下选项之一来定义命名空间:
-
使用
namespace-map
属性 -
使用
map
子元素 -
指定
ns-prefix
和ns-uri
属性
所有三个选项都是相互排斥的。 只能设置一个选项。
以下示例显示了使用 XPath 表达式的几种不同方法,包括前面提到的用于设置 XML 命名空间的选项:
<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 文档(代表两本书的订单):
<?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 表达式按预期工作:
<int-xml:xpath-expression expression="/order/orderItem" />
您可能期望相同的表达式也适用于以下 XML 文件:
<?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>
前面的示例看起来与前面的示例完全相同,但声明了一个默认命名空间。
但是,前面的 XPath 表达式 (/order/orderItem
) 在这种情况下失败。
为了解决此问题,您必须通过设置ns-prefix
和ns-uri
属性或通过设置namespace-map
属性。
命名空间 URI 必须与 XML 文档中声明的命名空间匹配。
在前面的示例中,即http://www.example.org/orders
.
但是,您可以任意选择命名空间前缀。事实上,提供空字符串实际上有效。(但是,不允许使用 null。)对于由空字符串组成的命名空间前缀,则 Xpath 表达式必须使用冒号 (“:”) 来指示默认命名空间。如果省略冒号,则 XPath 表达式不匹配。以下 XPath 表达式与前面示例中的 XML 文档匹配:
<int-xml:xpath-expression expression="/:order/:orderItem"
ns-prefix="" ns-uri="https://www.example.org/prodcuts"/>
您还可以提供任何其他任意选择的命名空间前缀。以下 XPath 表达式(使用myorder
命名空间前缀)也匹配:
<int-xml:xpath-expression expression="/myorder:order/myorder:orderItem"
ns-prefix="myorder" ns-uri="https://www.example.org/prodcuts"/>
命名空间 URI 是真正重要的信息,而不是前缀。Jaxen 很好地总结了这一点:
在 XPath 1.0 中,所有未带前缀的名称都是不限定的。不要求 XPath 表达式中使用的前缀与正在查询的文档中使用的前缀相同。只需要匹配命名空间 URI,而不是前缀。
转换 XML 有效负载
本节介绍如何转换 XML 有效负载
将 Transformer 配置为 Bean
本节将解释以下 transformer 的工作原理以及如何将它们配置为 bean:
所有 XML 转换器都扩展了AbstractTransformer
或AbstractPayloadTransformer
因此实施Transformer
.
在 Spring Integration 中将 XML 转换器配置为 bean 时,您通常会配置Transformer
结合MessageTransformingHandler
.
这允许将转换器用作端点。
最后,我们讨论命名空间支持,它允许将转换器配置为 XML 中的元素。
UnmarshallingTransformer
一UnmarshallingTransformer
让 XMLSource
通过使用 Spring OXM 的实现进行解组 Unmarshaller
.
Spring 的 Object/XML Mapping 支持提供了多种实现,这些实现支持使用 JAXB、Castor、JiBX 等进行编组和解编。
unmarshaller 需要一个Source
.
如果消息有效负载不是Source
,仍在尝试转换。
现在String
,File
,byte[]
和org.w3c.dom.Document
支持有效负载。
要创建自定义转换为Source
,您可以注入一个SourceFactory
.
如果您没有显式设置SourceFactory ,则UnmarshallingTransformer 默认情况下,设置为DomSourceFactory . |
从 5.0 版开始,UnmarshallingTransformer
还支持org.springframework.ws.mime.MimeMessage
作为传入的有效负载。当我们收到原始WebServiceMessage
通过 SOAP 使用 MTOM 附件。有关更多信息,请参阅 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 将对象图转换为 XMLMarshaller
. 默认情况下,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
将 payload 对象传递给Marshaller
. 但是,如果其布尔值extractPayload
属性设置为false
,整个Message
实例被传递给Marshaller
相反。 这对于Marshaller
接口,但通常,有效负载是用于封送的适当源对象,当您委托给各种Marshaller
实现。
XsltPayloadTransformer
这XsltPayloadTransformer
使用可扩展样式表语言转换 (XSLT) 转换 XML 有效负载。转换器的构造函数需要传入 Resource 或 Templates 的实例。传入Templates
实例允许对TransformerFactory
用于创建模板实例。
与UnmarshallingTransformer
这XsltPayloadTransformer
对Source
. 因此,如果消息有效负载不是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
instance)或传入预先创建的Templates
实例作为参考。
与封送转换器一样,可以通过指定result-factory
或result-type
属性。
当您需要在发送前转换结果时,您可以使用result-transformer
属性来引用ResultTransformer
.
如果指定result-factory 或result-type 属性,则alwaysUseResultFactory 基础上的属性XsltPayloadTransformer 设置为true 通过XsltPayloadTransformerParser . |
以下示例配置两个 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/>
元素。 在该元素上,您可以将expression
属性或value
属性。
这expression
属性应该是任何有效的 SpEL 表达式,其中Message
作为表达式求值上下文的根对象。
这value
属性(与任何value
在 Spring bean 中)允许您指定简单的标量值。
您还可以使用属性占位符(例如${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
.
现在我们可以声明 transformer,如下所示:
<int-xml:xslt-transformer input-channel="in" output-channel="fahrenheitChannel"
xsl-resource="classpath:noop.xslt" result-transformer="resultToDoc"/>
如果传入邮件的有效负载类型为Source
,然后,作为第一步,Result
通过使用ResultFactory
.
由于我们没有指定ResultFactory
,默认值DomResultFactory
,这意味着转换会产生DomResult
.
但是,正如我们指定的那样ResultTransformer
,它被使用并得到Message
有效负载的类型为Document
.
指定的ResultTransformer 被忽略String 或Document 负载。
如果传入邮件的有效负载类型为String ,则 XSLT 转换后的有效负载是String .
同样,如果传入消息的有效负载类型为Document ,则 XSLT 转换后的有效负载是 'Document'。 |
如果消息有效负载不是Source
一个String
或Document
,作为后备选项,我们尝试使用默认的SourceFactory
.
由于我们没有指定SourceFactory
显式地使用source-factory
属性,默认DomSourceFactory
被使用。
如果成功,则执行 XSLT 转换,就像有效负载的类型为Source
,如前几段所述。
这DomSourceFactory 支持创建DOMSource 从Document 一个File 或String 有效载荷。 |
下一个 transformer 声明将result-type
使用StringResult
作为其价值。
这result-type
在内部由StringResultFactory
.
因此,您还可以添加对StringResultFactory
,通过使用result-factory
属性,这将是相同的。
以下示例显示了 transformer 声明:
<int-xml:xslt-transformer input-channel="in" output-channel="fahrenheitChannel"
xsl-resource="classpath:noop.xslt" result-transformer="resultToDoc"
result-type="StringResult"/>
因为我们使用ResultFactory
这alwaysUseResultFactory
属性的XsltPayloadTransformer
class 被隐式设置为true
.
因此,引用的ResultToDocumentTransformer
被使用。
因此,如果将类型为String
,生成的有效负载类型为Document
.
XsltPayloadTransformer
和<xsl:output method="text"/>
<xsl:output method="text"/>
告诉 XSLT 模板仅从输入源生成文本内容。在这种特殊情况下,我们没有理由使用DomResult
. 因此,XsltPayloadTransformer
默认为StringResult
如果输出属性调用method
的javax.xml.transform.Transformer
返回text
. 此强制独立于入站有效负载类型执行。此行为仅适用于您设置的result-type
属性或result-factory
属性的<int-xml:xslt-transformer>
元件。
使用 XPath 转换 XML 消息
在消息转换方面,XPath 是转换具有 XML 有效负载的消息的好方法。您可以通过使用<xpath-transformer/>
元素。
简单的 XPath 转换
考虑以下转换器配置:
<int-xml:xpath-transformer input-channel="inputChannel" output-channel="outputChannel"
xpath-expression="/person/@name" />
还要考虑以下事项Message
:
Message<?> message =
MessageBuilder.withPayload("<person name='John Doe' age='42' married='true'/>").build();
将此消息发送到 'inputChannel' 后,之前配置的 XPath 转换器将此 XML 消息转换为简单的Message
有效负载为“John Doe”,所有这些都基于xpath-expression
属性。
XPath 还允许您将提取的元素简单转换为所需类型。有效的返回类型在javax.xml.xpath.XPathConstants
并遵循javax.xml.xpath.XPath
接口。
以下常量由XPathConstants
类:BOOLEAN
,DOM_OBJECT_MODEL
,NODE
,NODESET
,NUMBER
和STRING
.
您可以使用evaluation-type
属性的<xpath-transformer/>
元素,如以下示例所示(两次):
<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
属性,如以下示例所示:
<int-xml:xpath-transformer input-channel="nodeMapperInput" xpath-expression="/person/@age"
node-mapper="testNodeMapper" output-channel="output"/>
以下示例显示了NodeMapper
适用于上述示例的实现:
class TestNodeMapper implements NodeMapper {
public Object mapNode(Node node, int nodeNum) throws DOMException {
return node.getTextContent() + "-mapped";
}
}
XML 有效负载转换器
您还可以使用org.springframework.integration.xml.XmlPayloadConverter
以提供更精细的转换。以下示例演示如何定义一个:
<int-xml:xpath-transformer input-channel="customConverterInput"
output-channel="output" xpath-expression="/test/@type"
converter="testXmlPayloadConverter" />
以下示例显示了XmlPayloadConverter
适用于上述示例的实现:
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
,InputStream
和byte[]
负载。
如果您需要扩展到该默认实现的功能之外,则上游Transformer
可能比在此处提供对此策略的自定义实现的引用更好的选择。
拆分 XML 消息
XPathMessageSplitter
支持具有String
或Document
负载。
拆分器使用提供的 XPath 表达式将有效负载拆分为多个节点。
默认情况下,这会导致每个Node
实例成为新消息的有效负载。
当每条消息应为Document
,您可以将createDocuments
旗。
其中String
有效负载被传入,有效负载被转换,然后拆分,然后转换回许多String
消息。
XPath 拆分器实现MessageHandler
因此,应与适当的端点一起配置(有关更简单的配置替代方案,请参阅以下示例之后的命名空间支持示例)。
以下示例配置了一个使用XPathMessageSplitter
:
<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 拆分器命名空间支持允许您创建具有输入通道和输出通道的消息端点,如以下示例所示:
<!-- 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
财产:
<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.2
这XPathMessageSplitter
暴露了一个iterator
选项作为boolean
标志(默认为true
). 这允许在下游流中“流式传输”拆分节点。使用iterator
mode 设置为true
,每个节点在迭代时进行转换。 什么时候false
,在拆分节点开始发送到输出通道之前,所有条目都会首先进行转换。(您可以将区别视为“转换、发送、转换、发送”与“转换、转换、发送、发送”。有关更多信息,请参阅拆分器。
使用 XPath 路由 XML 消息
与基于 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 表达式被计算为 typeNODESET
并转换为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
表达式的结果是两个值 (responderA
和responderB
),但您不想将响应方名称耦合到通道名称,则可以提供其他映射配置,例如:
<!-- 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 表达式的计算结果可能为 typeString
从一开始。
例如,考虑以下 XPath 表达式:
name(./node())
此表达式返回根节点的名称。
如果默认评估类型NODESET
,则会导致异常。
对于这些方案,您可以使用evaluate-as-string
属性,用于管理评估类型。
是的FALSE
默认情况下。
但是,如果将其设置为TRUE
这String
使用评估类型。
XPath 1.0 指定了 4 种数据类型:
当 XPath 路由器使用可选的 有关详细信息,请参阅: |
例如,如果我们想根据根节点的名称进行路由,可以使用以下配置:
<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
属性。
如果未显式提供此引用,则DefaultXmlPayloadConverter
被使用。
在大多数情况下,它应该足够了,因为它可以从 Node、Document、Source、File 和 String 类型的有效负载进行转换。
如果您需要扩展到该默认实现的功能之外,那么在大多数情况下,上游 Transformer 通常是更好的选择,而不是在此处提供对此策略的自定义实现的引用。
XPath 标头扩充器
XPath 标头扩充器定义了一个标头扩充器消息转换器,该转换器根据消息有效负载评估 XPath 表达式,并将评估结果插入到消息头中。
以下列表显示了所有可用的配置参数:
<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_RESULT 和NODE_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
.
有关更多详细信息,请参阅过滤器。 |
要使用 XPath 过滤器,您至少必须通过声明xpath-expression
元素或通过引用 XPath 表达式xpath-expression-ref
属性。
如果提供的 XPath 表达式计算结果为boolean
值,则不需要进一步的配置参数。
但是,如果 XPath 表达式的计算结果为String
,则应将match-value
属性,评估结果与之匹配。
match-type
有三个选项:
-
exact
:对应于equals
上java.lang.String
. 底层实现使用StringValueTestXPathMessageSelector
-
case-insensitive
:对应于equals-ignore-case
上java.lang.String
. 底层实现使用StringValueTestXPathMessageSelector
-
regex
:匹配作一java.lang.String
. 底层实现使用RegexTestXPathMessageSelector
当提供 'match-type' 值 'regex' 时,与match-value
属性必须是有效的正则表达式。
以下示例显示了xpath-filter
元素:
<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 版开始,提供了内置的#xpath
SpEL 函数,该函数调用XPathUtils.evaluate(…)
static 方法。此方法委托给org.springframework.xml.xpath.XPathExpression
. 以下列表显示了一些用法示例:
<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_list
和document_list
) 或org.springframework.xml.xpath.NodeMapper
实例。 默认情况下,#xpath
SpEL 函数返回一个String
XPath 评估的表示形式。
要启用#xpath SpEL 函数,您可以添加spring-integration-xml.jar 到类路径。您无需声明 Spring Integration XML 命名空间中的任何组件。 |
有关详细信息,请参阅“'Spring 表达式语言 (SpEL)”。
XML 验证过滤器
XML 验证过滤器允许您根据提供的架构实例验证传入消息。支持以下架构类型:
-
xml-schema (https://www.w3.org/2001/XMLSchema)
-
放松-NG (https://relaxng.org)
验证失败的消息可以静默删除,也可以转发到可定义的discard-channel
. 此外,您可以将此过滤器配置为抛出Exception
以防验证失败。
以下列表显示了所有可用的配置参数:
<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-schema 或relax-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 过滤器一起使用的轮询器。 自选。 |