轉換 XML 載荷
本節介紹如何轉換 XML 載荷
將 Transformer 配置為 Bean
本節將解釋以下轉換器的工作原理以及如何將它們配置為 Bean
所有 XML 轉換器都擴充套件了 AbstractTransformer
或 AbstractPayloadTransformer
,因此實現了 Transformer
。在 Spring Integration 中將 XML 轉換器配置為 Bean 時,通常會結合 MessageTransformingHandler
配置 Transformer
。這使得轉換器可以用作端點。最後,我們將討論名稱空間支援,它允許將轉換器配置為 XML 中的元素。
UnmarshallingTransformer
一個 UnmarshallingTransformer
允許使用 Spring OXM 的 Unmarshaller
實現來解組 XML Source
。Spring 的物件/XML 對映支援提供了多種實現,支援使用 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
作為入站載荷。當透過 SOAP 接收帶有 MTOM 附件的原始 WebServiceMessage
時,這非常有用。有關更多資訊,請參閱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 Marshaller
將物件圖轉換為 XML。預設情況下,MarshallingTransformer
返回一個 DomResult
。但是,您可以透過配置備選的 ResultFactory
(例如 StringResultFactory
)來控制結果的型別。在許多情況下,將載荷轉換為另一種 XML 格式更方便。為此,請配置一個 ResultTransformer
。Spring Integration 提供了兩種實現:一種轉換為 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
將載荷物件傳遞給 Marshaller
。但是,如果其布林屬性 extractPayload
設定為 false
,則會將整個 Message
例項傳遞給 Marshaller
。這對於 Marshaller
介面的某些自定義實現可能有用,但通常情況下,當委託給各種 Marshaller
實現時,載荷是適合用於編組的源物件。
XsltPayloadTransformer
XsltPayloadTransformer
使用 Extensible Stylesheet Language Transformations (XSLT) 來轉換 XML 載荷。轉換器的建構函式需要傳入 Resource 或 Templates 例項。傳入 Templates
例項可以更好地配置用於建立模板例項的 TransformerFactory
。
與 UnmarshallingTransformer
類似,XsltPayloadTransformer
對 Source
例項執行實際的 XSLT 轉換。因此,如果訊息載荷不是 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
。
有關更多資訊和示例,請參閱名稱空間配置和 Result Transformer。
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"/>
如果提供的結果型別不滿足需求,您可以使用 result-factory
屬性提供對 ResultFactory
自定義實現的引用,作為設定 result-type
屬性的替代方案。result-type
和 result-factory
屬性互斥。
在內部,StringResult 和 DomResult 結果型別分別由 ResultFactory 實現 StringResultFactory 和 DomResultFactory 表示。 |
使用 XsltPayloadTransformer
XsltPayloadTransformer
的名稱空間支援允許您傳入 Resource
(以便建立 Templates
例項)或將預先建立的 Templates
例項作為引用傳入。與編組轉換器一樣,您可以透過指定 result-factory
或 result-type
屬性來控制結果輸出的型別。當需要在傳送之前轉換結果時,您可以使用 result-transformer
屬性引用 ResultTransformer
的實現。
如果您指定了 result-factory 或 result-type 屬性,則底層 XsltPayloadTransformer 的 alwaysUseResultFactory 屬性將被 XsltPayloadTransformerParser 設定為 true 。 |
以下示例配置了兩個 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/>
元素配置單個 XSLT 引數。在該元素上,您可以設定 expression
屬性或 value
屬性。expression
屬性應為任何有效的 SpEL 表示式,其中 Message
是表示式求值上下文的根物件。value
屬性(與 Spring Bean 中的任何 value
一樣)允許您指定簡單的標量值。您還可以使用屬性佔位符(例如 ${some.value}
)。因此,透過 expression
和 value
屬性,您可以將 XSLT 引數對映到 Message
的任何可訪問部分以及任何文字值。
從 Spring Integration 3.0 開始,您現在可以透過設定 transformer-factory-class
屬性來指定轉換器工廠類名。
名稱空間配置和 Result Transformer
我們在使用 ResultTransformer
實現中介紹了使用結果轉換器。本節中的示例使用 XML 名稱空間配置來說明幾個特殊用例。首先,我們定義 ResultTransformer
,如下例所示
<beans:bean id="resultToDoc" class="o.s.i.xml.transformer.ResultToDocumentTransformer"/>
此 ResultTransformer
接受 StringResult
或 DOMResult
作為輸入,並將輸入轉換為 Document
。
現在我們可以宣告轉換器,如下所示
<int-xml:xslt-transformer input-channel="in" output-channel="fahrenheitChannel"
xsl-resource="classpath:noop.xslt" result-transformer="resultToDoc"/>
如果入站訊息的載荷型別為 Source
,那麼第一步是使用 ResultFactory
確定 Result
。由於我們沒有指定 ResultFactory
,因此使用了預設的 DomResultFactory
,這意味著轉換產生一個 DomResult
。
然而,由於我們指定了一個 ResultTransformer
,它會被使用,並且生成的 Message
載荷型別為 Document
。
對於 String 或 Document 載荷,指定的 ResultTransformer 會被忽略。如果入站訊息的載荷型別為 String ,則 XSLT 轉換後的載荷是一個 String 。同樣,如果入站訊息的載荷型別為 Document ,則 XSLT 轉換後的載荷是一個 Document 。 |
如果訊息載荷不是 Source
、String
或 Document
,則作為備選方案,我們嘗試使用預設的 SourceFactory
建立一個 Source
。由於我們沒有透過 source-factory
屬性顯式指定 SourceFactory
,因此使用了預設的 DomSourceFactory
。如果成功,XSLT 轉換將執行,如同載荷是 Source
型別一樣,如前幾段所述。
DomSourceFactory 支援從 Document 、File 或 String 載荷建立 DOMSource 。 |
下一個轉換器宣告添加了一個 result-type
屬性,其值為 StringResult
。result-type
在內部由 StringResultFactory
表示。因此,您也可以使用 result-factory
屬性新增對 StringResultFactory
的引用,效果是一樣的。以下示例展示了該轉換器宣告
<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
。
因此,如果您轉換 String
型別的載荷,則生成的載荷型別為 Document
。
[[xsltpayloadtransformer-and-<xsl:output-method=-text-/>]] === XsltPayloadTransformer
和 <xsl:output method="text"/>
<xsl:output method="text"/>
告訴 XSLT 模板僅從輸入源生成文字內容。在這種特殊情況下,我們沒有理由使用 DomResult
。因此,如果底層 javax.xml.transform.Transformer
的名為 method
的輸出屬性返回 text
,則 XsltPayloadTransformer
會預設使用 StringResult
。此強制轉換獨立於入站載荷型別執行。此行為僅在您為 <int-xml:xslt-transformer>
元件設定 result-type
屬性或 result-factory
屬性時可用。