領先一步
VMware 提供培訓和認證,助您加速進步。
瞭解更多我們很高興地宣佈 Spring Integration 的 Java DSL 擴充套件的第二個里程碑版本已釋出!
org.springframework.integration:spring-integration-java-dsl:1.0.0.M2 構件可在 Spring IO Milestone Repository 中獲取。
Milestone 2 包含多項錯誤修復、一些新功能和進一步的改進。
感謝所有嘗試了 Milestone 1、提供反饋、報告問題並分享想法的人。
以下是自 Milestone 1 以來主要變更的摘要:
Lambda 處理程式
您可能已經注意到,Java 8 Lambda 的使用是使此 DSL 方便且易於閱讀的強大工具。我們收到的一個社群請求是允許在 .handle() EIP 方法中宣告 Lambda,而不是必須宣告一個 POJO 並將其用作方法呼叫。但一個擔憂是不要丟失“執行時型別轉換”。然而,您 無法獲取 Lambda 的泛型型別。經過一些調查,我們透過新增一個 type 引數找到了解決方案。因此,已向 IntegrationFlowBuilder 添加了幾個新方法。
<P> IntegrationFlowBuilder handle(GenericHandler<P> handler)
<P> IntegrationFlowBuilder handle(GenericHandler<P> handler,
EndpointConfigurer<GenericEndpointSpec<ServiceActivatingHandler>> endpointConfigurer)
<P> IntegrationFlowBuilder handle(Class<P> payloadType, GenericHandler<P> handler)
<P> IntegrationFlowBuilder handle(Class<P> payloadType, GenericHandler<P> handler,
EndpointConfigurer<GenericEndpointSpec<ServiceActivatingHandler>> endpointConfigurer)
如果您使用帶有顯式 payloadType 引數的方法變體,並且 handler 是一個 Lambda,最後一個引數將包裝到 LambdaMessageProcessor,並帶有一個 ConversionService。訊息 payload 將在執行時轉換為適當的 type。透過這種方式,我們實現了更好的鬆散耦合。以下是一個演示的簡單示例:
@Bean
public IntegrationFlow integerFlow() {
return IntegrationFlows.from("input")
.<byte[], String>transform(p - > new String(p, "UTF-8"))
.handle(Integer.class, (p, h) -> p * 2)
.get();
}
ConversionService 防止了 ClassCastException: String cannot be cast to Integer。
相同的附加型別引數已新增到其他帶有 Lambda 的 EIP 方法:.transform()、.filter()、.split() 等。
Transformers 工廠
方便、流暢的 Transformers 工廠已新增,可在 .transform() EIP 方法中用作內聯目標物件定義。
@Bean
public IntegrationFlow transformFlow() {
return IntegrationFlows.from("input")
.transform(Transformers.xpath("/root/myJson", XPathEvaluationType.STRING_RESULT))
.transform(Transformers.fromJson(MyPojo.class))
.transform(Transformers.serializer())
.get();
}
這避免了使用 setter 的不方便編碼,並使流程定義更加直接。請注意,Transformers 可用於將目標 Transformer 宣告為 @Bean,並再次在 IntegrationFlow 定義中使用它們。儘管如此,DSL 解析器會處理內聯物件的 bean 宣告,如果它們尚未定義為 bean。
.gateway() EIP 方法
由於 IntegrationFlow 定義看起來類似於 Spring Integration XML 中的 <chain>,因此我們引入了 .gateway() EIP 方法,它在 <chain> 中的作用與 <gateway> 相同 - 將訊息傳送到另一個訊息流的 requestChannel,並等待其 replyChannel 的結果,或者預設情況下是 TemporaryReplyChannel。
@Bean
@DependsOn("gatewayRequestFlow")
public IntegrationFlow gatewayFlow() {
return IntegrationFlows.from("gatewayInput")
.gateway("gatewayRequest", g -> g.errorChannel("gatewayError").replyTimeout(10L))
.get();
}
@Bean
public IntegrationFlow gatewayRequestFlow() {
return IntegrationFlows.from("gatewayRequest")
.filter("foo"::equals, f -> f.throwExceptionOnRejection(true))
.<String, String>transform(String::toUpperCase)
.get();
}
特定協議的介面卡
當然,Spring Integration 的許多價值在於與某些外部系統的互動,而協議介面卡提供了此功能。藉助 Spring Integration Java DSL,我們可以繼續使用通用的 bean 定義(@Bean)來處理任何最終系統介面卡(例如 MarshallingWebServiceInboundGateway),但 DSL 的目的是提供一個更高級別的 API 來宣告元件,方式與 Spring Integration XML 配置提供的類似。
既然您現在熟悉我們的 Builder 和 Lambda 功能,我們將在此基礎上構建。已引入類,其中包含一組靜態方法,用於委託給某個底層 IntegrationComponentSpec<S, P> 實現。這些類可以被認為是“名稱空間工廠”,因為它們的作用與來自具體協議特定 Spring Integration 模組的元件的 XML 名稱空間相同。目前,Spring Integration Java DSL 只支援 Amqp 和 Jms 名稱空間工廠。
@Bean
public IntegrationFlow amqpFlow() {
return IntegrationFlows.from(Amqp.inboundGateway(this.rabbitConnectionFactory, queue()))
.transform("hello "::concat)
.transform(String.class, String::toUpperCase)
.get();
}
@Bean
public IntegrationFlow amqpOutboundFlow() {
return IntegrationFlows.from("amqpOutboundInput")
.handle(Amqp.outboundAdapter(this.amqpTemplate).routingKeyExpression("headers.routingKey"))
.get();
}
@Bean
public IntegrationFlow jmsInboundFlow() {
return IntegrationFlows
.from(Jms.inboundAdapter(this.jmsConnectionFactory)
.configureJmsTemplate(t ->
t.deliveryPersistent(true)
.jmsMessageConverter(myMessageConverter()))
.destination("jmsInbound"))
.<String, String>transform(String::toUpperCase)
.channel(this.jmsOutboundInboundReplyChannel())
.get();
}
@Bean
public IntegrationFlow jmsOutboundGatewayFlow() {
return IntegrationFlows.from("jmsOutboundGatewayChannel")
.handle(Jms.outboundGateway(this.jmsConnectionFactory)
.replyContainer(c ->
c.concurrentConsumers(3)
.sessionTransacted(true))
.requestDestination("jmsPipelineTest"))
.get();
}
我們在此展示了名稱空間工廠作為內聯介面卡宣告的用法,然而它們也可以用於 @Bean 定義,以使 IntegrationFlow 方法鏈更易讀。
在投入其他名稱空間工廠的精力之前,我們正在徵求社群對此的反饋;我們還希望對我們應該支援的下一個介面卡/閘道器進行一些優先順序排序。
請確保在類路徑中有具體的 spring-integration-[PROTOCOL].jar 及其必需的依賴項,因為 spring-integration-java-dsl 將它們宣告為 optional,以避免不必要的最終應用程式開銷。
DSL 解析器的更改
儘管 M2 版本的總體目標是解決 DSL 解析器放置不當的關鍵問題,但現在它已從 IntegrationConfigurationBeanFactoryPostProcessor 移至 IntegrationFlowBeanPostProcessor,Spring Integration Java DSL 不再影響應用程式上下文 - 它只遵循標準的 Spring bean 定義生命週期。您可能需要對現有的 DSL 應用程式進行一些更改才能使用此版本。
在大多數情況下,這僅限於 channel 自動宣告,即我們不定義顯式的 MessageChannel bean 定義,而是從整合元件引用它。如果您注意到上面 .gateway() 示例中使用了 @DependsOn 註解。這是因為 bean 是逐個註冊和初始化的,正如它們在 @Configuration 類中宣告的那樣。由於我們不使用 MessageChannel 的 bean 定義,應用程式上下文無法自動為使用通道的 bean 宣告 dependsOn,另一方面,我們根本沒有宣告 MessageChannel bean,我們只有一個選擇,那就是依賴 IntegrationFlow bean。
因此,您可以顯式宣告 MessageChannel bean,或者對宣告隱式通道的下游 IntegrationFlow 使用適當的 IntegrationFlow bean 定義上的 @DependsOn。
總結
有關更多資訊,請參閱上述 參考手冊。並檢視 [網路研討會回放:Spring Integration 4.0 - 新的疆域] (https://springframework.tw/blog/2014/05/15/webinar-replay-spring-integration-4-0-the-new-frontier),其中透過“即時編碼”介紹了 Spring Integration Java DSL。
一如既往:請隨時分享您的想法和反饋:StackOverflow(spring-integration 標籤)、Spring JIRA。
SpringOne 2GX 2014 即將到來
請立即預訂您在 達拉斯舉行的 SpringOne2GX(9 月 8 日至 11 日)的席位。這是深入瞭解所有最新動態並提供直接反饋的最佳機會。今年預計將有許多重要的公告。我們預計將有多場深入的 Spring Integration 會議。