Spring Integration Java DSL 里程碑 2 釋出

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

我們很高興宣佈,用於 Spring Integration 的 Java DSL 擴充套件的**第二個里程碑版本**已經發布!

構件 org.springframework.integration:spring-integration-java-dsl:1.0.0.M2 可從 Spring IO 里程碑倉庫獲取。

里程碑 2 包含了一些錯誤修復、一些新特性和進一步改進。

感謝所有嘗試了里程碑 1、提供了反饋、提出了問題並分享了想法的人們。

以下是自 里程碑 1 以來的主要變更摘要

Lambda 處理器

正如您可能已經注意到的,使用 Java 8 Lambdas 是使這個 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 的方法變體,最後一個引數將封裝到帶有 ConversionServiceLambdaMessageProcessor 中。訊息的 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 錯誤。

同樣附加的型別引數已新增到帶有 Lambdas 的其他 EIP 方法中:.transform().filter().split() 等。

轉換器工廠

已新增方便、流暢的 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 定義中使用它們。然而,如果內聯物件尚未定義為 bean,DSL 解析器會負責處理它們的 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,我們可以繼續對任何終端系統介面卡(例如 MarshallingWebServiceInboundGateway)使用通用的 bean 定義(@Bean),但 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 方法鏈更具可讀性。

在我們將精力投入到其他工廠之前,我們正在徵集社群對這些名稱空間工廠的反饋;我們也很希望瞭解接下來我們應該優先支援哪些介面卡/閘道器。

請確保您的 classpath 中有具體的 spring-integration-[PROTOCOL].jar 及其必需的依賴項,因為 spring-integration-java-dsl 將它們宣告為 optional,以避免不必要的終端應用程式開銷。

DSL 解析器變更

然而,這次 M2 版本的主要目的是解決 DSL 解析器位置錯誤的嚴重問題。現在它已從 IntegrationConfigurationBeanFactoryPostProcessor 移至 IntegrationFlowBeanPostProcessor,Spring Integration Java DSL 不再影響應用程式上下文——它僅遵循標準的 Spring bean 定義生命週期。您可能需要對現有的 DSL 應用程式進行一些更改才能使用此版本。

在大多數情況下,這僅限於 channel auto-declaration,即我們沒有定義顯式的 MessageChannel bean 定義,而是從整合元件中引用它。如果您注意到上面的 .gateway() 示例中我們使用了 @DependsOn 註解。這是因為 bean 是在 @Configuration 類中宣告時逐個註冊和初始化的。由於我們沒有為 MessageChannel 使用 bean 定義,應用程式上下文無法自動為使用 channel 的 bean 宣告 dependsOn,而且從另一方面來說,我們根本沒有宣告 MessageChannel bean,我們只有一個選擇就是依賴於 IntegrationFlow bean。

因此,您可以選擇顯式宣告 MessageChannel bean,或者在宣告隱式 channel 的下游 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 即將到來

請儘快預訂 9 月 8-11 日在德克薩斯州達拉斯舉行的 SpringOne2GX 的席位。這絕對是第一手瞭解最新動態並提供直接反饋的最佳機會。預計今年將有許多重要的新公告。我們預計將有幾個深入的 Spring Integration 會議。

獲取 Spring 新聞通訊

訂閱 Spring 新聞通訊,保持聯絡

訂閱

先人一步

VMware 提供培訓和認證,助您快速提升。

瞭解更多

獲取支援

Tanzu Spring 透過一項簡單的訂閱提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位制檔案。

瞭解更多

近期活動

檢視 Spring 社群的所有近期活動。

檢視全部