Spring Integration Java DSL Milestone 2 已釋出

釋出 | Artem Bilan | 2014 年 6 月 18 日 | ...

我們很高興地宣佈 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 配置提供的類似。

既然您現在熟悉我們的 BuilderLambda 功能,我們將在此基礎上構建。已引入類,其中包含一組靜態方法,用於委託給某個底層 IntegrationComponentSpec<S, P> 實現。這些類可以被認為是“名稱空間工廠”,因為它們的作用與來自具體協議特定 Spring Integration 模組的元件的 XML 名稱空間相同。目前,Spring Integration Java DSL 只支援 AmqpJms 名稱空間工廠。

@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。

一如既往:請隨時分享您的想法和反饋:StackOverflowspring-integration 標籤)、Spring JIRA

SpringOne 2GX 2014 即將到來

請立即預訂您在 達拉斯舉行的 SpringOne2GX(9 月 8 日至 11 日)的席位。這是深入瞭解所有最新動態並提供直接反饋的最佳機會。今年預計將有許多重要的公告。我們預計將有多場深入的 Spring Integration 會議。

獲取 Spring 新聞通訊

透過 Spring 新聞通訊保持聯絡

訂閱

領先一步

VMware 提供培訓和認證,助您加速進步。

瞭解更多

獲得支援

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位制檔案,只需一份簡單的訂閱。

瞭解更多

即將舉行的活動

檢視 Spring 社群所有即將舉行的活動。

檢視所有