领先一步
VMware 提供培训和认证,以加速您的进步。
了解更多我们很高兴地宣布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 配置提供的方式声明组件。
既然您现在熟悉了我们的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 应用程序进行一些更改才能使用此版本。
在大多数情况下,这仅限于通道自动声明
,当我们没有定义显式的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 是通过“现场编码”介绍的。
照常:请随时分享您的想法和反馈:StackOverflow(spring-integration
标签)、Spring JIRA。
SpringOne 2GX 2014 即将到来
在德克萨斯州达拉斯举行的 SpringOne2GX上预留您的位置,时间为 9 月 8 日至 11 日。这是了解所有正在发生的事情并提供直接反馈的最佳机会。预计今年将有许多重大的新公告。我们预计将举办一些深入的 Spring Integration 会议。