Spring Integration Java DSL 第二个里程碑版本发布

发布 | 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 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工厂已添加,可在.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方法链更易读。

在我们投入精力开发其他命名空间工厂之前,我们正在征求社区对这些命名空间工厂的反馈;我们也希望优先考虑我们接下来应该支持哪些适配器/网关。

请确保类路径上有具体的spring-integration-[PROTOCOL].jar及其所需的依赖项,因为spring-integration-java-dsl将其声明为optional以避免不必要的最终应用程序开销。

DSL 解析器更改

尽管如此,此 M2 版本的总体目的是解决 DSL 解析器位置错误的关键问题。现在它已从IntegrationConfigurationBeanFactoryPostProcessor移动到IntegrationFlowBeanPostProcessor,并且 Spring Integration Java DSL 不会再影响应用程序上下文 - 它只是遵循标准的 Spring bean 定义生命周期。您可能需要对现有 DSL 应用程序进行一些更改才能使用此版本。

在大多数情况下,这仅限于通道自动声明,当我们没有定义显式的MessageChannel bean 定义,而是从集成组件引用它时。如果您在上面的.gateway()示例中注意到,我们使用了@DependsOn注解。这是因为 bean 是一个接一个地注册和初始化的,因为它们是在@Configuration类中声明的。由于我们不使用MessageChannel的 bean 定义,因此应用程序上下文无法自动为使用通道的 bean 声明dependsOn,并且从另一方面,我们根本没有声明MessageChannel bean,我们只有一个选择依赖于IntegrationFlow bean。

因此,您可以选择显式声明MessageChannel bean,或者在适当的IntegrationFlow bean 定义上使用@DependsOn,用于声明隐式通道的下游IntegrationFlow

总结

请参阅上面提到的参考手册以获取更多信息。并查看[网络研讨会回放:Spring Integration 4.0 - 新前沿] (https://springframework.org.cn/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 社区中所有即将举行的活动。

查看全部