XML 支持 - 处理 XML 有效负载
XML 支持 - 处理 XML 有效负载
Spring 集成的 XML 支持通过以下组件扩展了 Spring 集成的核心:
您需要将此依赖项包含在您的项目中:
<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
payload 被转换为 required 类型,然后转换回String
.
需要DocumentBuilder
如果未提供命名空间感知实例,请创建一个命名空间感知实例。
当您需要更好地控制文档创建时,可以提供适当配置的DocumentBuilder
.
命名空间支持
Spring 集成 XML 模块中的所有组件都提供名称空间支持。 为了启用名称空间支持,你需要导入 Spring 集成 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 集成 XML 模块中的许多组件都可以使用 XPath 表达式。
这些组件中的每一个要么引用已定义为顶级元素的 XPath 表达式,要么使用嵌套的<xpath-expression/>
元素。
所有形式的 XPath 表达式都会导致创建一个XPathExpression
使用 Springorg.springframework.xml.xpath.XPathExpressionFactory
.
创建 XPath 表达式时,将使用 Classpath 上可用的最佳 XPath 实现(JAXP 1.3+ 或 Jaxen,首选 JAXP)。
在内部, Spring 集成使用 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
namespace 前缀)也匹配:
<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
本节将解释以下转换器的工作原理以及如何将它们配置为 bean:
所有 XML 转换器都扩展了AbstractTransformer
或AbstractPayloadTransformer
并因此实施Transformer
.
在 Spring 集成中将 XML 转换器配置为 bean 时,通常会将Transformer
与MessageTransformingHandler
.
这允许将转换器用作终端节点。
最后,我们讨论命名空间支持,它允许将转换器配置为 XML 中的元素。
解组转换器
一UnmarshallingTransformer
让 XMLSource
通过使用 Spring OXM 的实现进行解组 Unmarshaller
.
Spring 的 Object/XML Mapping 支持提供了多种实现,这些实现通过使用 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
作为传入的负载。
当我们收到 raw 时,这可能很有用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
payloads 直接受支持。
要创建到Source
中,您可以注入SourceFactory
.
如果SourceFactory 未显式设置,则XsltPayloadTransformer 设置为DomSourceFactory . |
默认情况下,XsltPayloadTransformer
创建一条消息Result
payload 的 intent 与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 集成提供了两个具体的ResultTransformer
实现:
默认情况下,MarshallingTransformer
始终返回Result
.
通过指定ResultTransformer
中,您可以自定义返回的负载类型。
对于XsltPayloadTransformer
.
默认情况下,如果输入有效负载是String
或Document
这resultTransformer
属性被忽略。
但是,如果输入负载是Source
或任何其他类型,resultTransformer
属性。
此外,您还可以设置alwaysUseResultFactory
property 设置为true
,这也会导致指定的resultTransformer
以供使用。
有关更多信息和示例,请参阅命名空间配置和结果转换器。
XML 转换器的命名空间支持
Spring 集成 XML 名称空间中提供了对所有 XML 转换器的名称空间支持,前面显示了该名称空间的模板。
对 transformers 的命名空间支持会创建一个EventDrivenConsumer
或PollingConsumer
,具体取决于提供的输入通道的类型。
命名空间支持旨在通过允许创建使用一个元素的端点和转换器来减少 XML 配置的数量。
使用UnmarshallingTransformer
命名空间对UnmarshallingTransformer
如下所示。
由于命名空间创建的是端点实例而不是转换器,因此您可以在元素中嵌套 Poller 来控制 input 通道的轮询。
以下示例显示了如何执行此作:
<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 result 类型由ResultFactory 实现:StringResultFactory 和DomResultFactory 分别。 |
使用XsltPayloadTransformer
命名空间支持XsltPayloadTransformer
允许您传入Resource
(为了创建Templates
实例)或传入预先创建的Templates
实例作为参考。
与编组转换器一样,您可以通过指定result-factory
或result-type
属性。
当您需要在发送前转换结果时,您可以使用result-transformer
attribute 来引用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
headers 来协助转换。
例如,您可能需要访问某些Message
headers 并将它们作为参数传递给转换器(例如transformer.setParameter(..)
).
Spring 集成提供了两种便捷的方法来实现这一目标,如下例所示:
<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
作为 expression 求值上下文的根对象。
这value
属性(与任何value
)允许您指定简单的标量值。
您还可以使用属性占位符(例如${some.value}
).
因此,使用expression
和value
属性,您可以将 XSLT 参数映射到Message
以及任何 Literal 值。
从 Spring Integration 3.0 开始,你现在可以通过在 3.0 中设置transformer-factory-class
属性。
命名空间配置和结果转换器
我们介绍了 result transformer 的使用用ResultTransformer
实现.
本节中的示例使用 XML 命名空间配置来说明几个特殊用例。
首先,我们定义ResultTransformer
,如下例所示:
<beans:bean id="resultToDoc" class="o.s.i.xml.transformer.ResultToDocumentTransformer"/>
这ResultTransformer
接受StringResult
或DOMResult
作为 input 进行转换,并将 input 转换为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
payload 的类型为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[]
负载。
如果您需要扩展该默认实现的功能之外,则 upstreamTransformer
可能比在此处提供对此策略的自定义实现的引用更好。
拆分 XML 消息
XPathMessageSplitter
支持带有String
或Document
负载。
拆分器使用提供的 XPath 表达式将负载拆分为多个节点。
默认情况下,这会导致每个Node
实例成为新消息的有效负载。
当每条消息都应该是一个Document
中,您可以设置createDocuments
旗。
其中 aString
payload 传入,则 payload 会被转换,然后被分割,然后再转换回String
消息。
XPath 拆分器实现MessageHandler
因此,应与相应的端点一起配置(有关更简单的配置替代方案,请参阅以下示例后面的命名空间支持示例)。
以下示例配置一个 Bean,该 Bean 使用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 splitter 命名空间支持允许您创建具有 input 通道和 output 通道的消息端点,如下例所示:
<!-- 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
flag(默认为true
).
这允许在下游流中 “流式处理” 拆分节点。
使用iterator
mode 设置为true
,则每个节点在迭代时都会进行转换。
什么时候false
,在开始将拆分节点发送到输出通道之前,首先转换所有条目。
(您可以将差异视为“转换、发送、转换、发送”与“转换、转换、发送、发送”。
有关更多信息,请参阅 Splitter 。
使用 XPath 路由 XML 消息
与基于 SPEL 的路由器类似, Spring 集成提供了对基于 XPath 表达式的路由消息的支持,这允许你创建具有 input 通道但没有输出通道的消息端点。 相反,一个或多个 output channel 是动态确定的。 以下示例说明如何创建此类路由器:
<int-xml:xpath-router id="orderTypeRouter" input-channel="orderChannel">
<int-xml:xpath-expression expression="/order/type"/>
</int-xml:xpath-router>
有关 Router 之间通用属性的概述,请参阅 Common Router Parameters。 |
在内部,XPath 表达式作为 type 进行评估NODESET
并转换为List<String>
,表示频道名称。
通常,此类列表包含单个通道名称。
但是,根据 XPath 表达式的结果,如果 XPath 表达式返回多个值,则 XPath 路由器也可以具有收件人列表路由器的特征。
在这种情况下,List<String>
包含多个频道名称。
因此,消息将发送到列表中的所有通道。
因此,假设传递给以下 router 配置的 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
expression 会生成两个值 (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>
of channel names,用于处理单通道场景以及多通道场景。
尽管如此,某些 XPath 表达式的计算结果可能是 typeString
从一开始。
例如,请考虑以下 XPath 表达式:
name(./node())
此表达式返回根节点的名称。
如果默认评估类型NODESET
,则会导致异常。
对于这些场景,您可以使用evaluate-as-string
属性,用于管理评估类型。
是的FALSE
默认情况下。
但是,如果将其设置为TRUE
这String
使用 evaluation type 。
XPath 1.0 指定了 4 种数据类型:
当 XPath Router 使用可选的 有关详细信息,请参阅: |
例如,如果我们想根据根节点的名称进行路由,我们可以使用以下配置:
<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 评估之前转换负载时要使用的 Converter。
因此,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 | 指定是否覆盖现有标头值的默认布尔值。 它仅对不提供自己的 'overwrite' 属性的子元素生效。 如果未设置 'default- overwrite' 属性,则指定的标头值不会覆盖任何具有相同标头名称的现有标头值。 自选。 |
2 | 基础 Bean 定义的 ID。 自选。 |
3 | 此终端节点的接收消息通道。 自选。 |
4 | 将扩充消息发送到的通道。 自选。 |
5 | 指定是否应跳过 null 值,例如可能从表达式计算返回的 null 值。
默认值为true .
如果 null 值应触发删除相应的标头,请将此项设置为false .
自选。 |
6 | 与 Header Enricher 一起使用的 Poller 。 自选。 |
7 | 要扩充的标头的名称。 命令的。 |
8 | XPath 评估所需的结果类型。
如果您没有设置header-type attribute,这是 header 值的类型。
允许使用以下值:BOOLEAN_RESULT ,STRING_RESULT ,NUMBER_RESULT ,NODE_RESULT 和NODE_LIST_RESULT .
如果未设置,则它在内部默认为XPathEvaluationType.STRING_RESULT .
自选。 |
9 | 标头值类型的完全限定类名。
XPath 评估的结果通过以下方式转换为此类型ConversionService .
这允许,例如,一个NUMBER_RESULT (double) 转换为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
:匹配作 1java.lang.String
. 底层实现使用RegexTestXPathMessageSelector
当提供 'regex' 的 'match-type' 值时,使用match-value
attribute 必须是有效的正则表达式。
以下示例显示了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 过滤器的 Poller。 自选。 |
#xpath SPEL 函数
Spring 集成,从 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 添加到 Classpath 中。
你不需要从 Spring 集成 XML 名称空间声明任何组件。 |
有关详细信息,请参阅“Spring 表达式语言 (SpEL)”。
XML 验证过滤器
XML 验证筛选器允许您根据提供的架构实例验证传入消息。 支持以下 Schema 类型:
-
xml-schema (https://www.w3.org/2001/XMLSchema)
-
relax-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 | 设置 Schema 类型。
可以是xml-schema 或relax-ng .
自选。
如果未设置,则默认为xml-schema ,在内部转换为org.springframework.xml.validation.XmlValidatorFactory#SCHEMA_W3C_XML . |
7 | 如果true 一个MessageRejectedException 如果提供的 Message 的有效负载验证失败,则引发。
默认为false 如果未设置。
自选。 |
8 | 对自定义的引用org.springframework.integration.xml.XmlPayloadConverter 策略。
自选。 |
9 | 对自定义的引用sorg.springframework.xml.validation.XmlValidator 策略。
您可以设置此属性或schema-location 属性,但不能同时实现两者。
自选。 |
10 | 用于 XPath 过滤器的 Poller。 自选。 |