领先一步
VMware 提供培训和认证,助您加速前进。
了解更多我们很高兴宣布 Spring Integration 2.0 的第一个发布候选版本! 下载 | 参考手册 | JavaDoc
我想借此机会提供一份概括性的“新特性是什么?”指南。新特性和改进实际上太多了,无法在一篇帖子中全部涵盖,但我将重点介绍一些亮点。随着我们接近 2.0 GA 版本发布,我们将发布更多博客。目前,这篇帖子大致基于我和 Oleg 上周在 SpringOne 大会上做的一个演讲。那个演讲主要是演示驱动的,代码在我们的Git 仓库中提供。
为了提供一些结构,我将按以下几个类别来介绍这些特性...
Spring Integration 2.0 直接构建在 Spring 3.0 之上。事实上,RC1 版本构建在 Spring 3.0.5 之上,而后者就在上周发布了。在这里,我们将介绍由于底层框架的重大升级而实现的一些最值得关注的特性。
现在,您可以在 Spring Integration 核心命名空间中的 transformer、router、filter、splitter、aggregator、service-activator 以及更多元素中使用 SpEL 表达式。例如,如果您可以根据载荷对象中的简单属性来评估 Filter 规则,只需执行以下操作
<filter input-channel="numbers" expression="payload > 0" output-channel="positives"/>
在许多情况下,'expression' 属性可以替代 'ref' 和 'method' 的用法,以及 'ref' 指向的 POJO。另一方面,即使您确实需要在 Spring 上下文中的 bean 上执行方法,简单的 'method' 属性也可能不够。例如,您可能需要控制传递给方法的多个参数。虽然方法参数上的 @Payload 和 @Header 注解提供了一种选择,但有时将这些细节保留在配置中而不是代码中会更好。这里是使用 SpEL BeanResolver 策略而不是 'ref' 的一个示例
<router input-channel="accounts"
expression="@accountService.getAccountType(payload.accountId, payload.address.country)"/>
您可以定义一个名为“integrationConversionService”的 ConversionService bean,然后注册您想要的任何Converter(如有必要,包括您自己的自定义实现)。在 Spring Integration 中,该 ConversionService 有两个使用的地方。对于即时转换,您可以向 <channel> 元素添加一个“datatype”属性,并提供您希望在该通道上允许的 Class 的完全限定名。这里是一个示例
<channel id="datatypeChannel" datatype="example.Foo"/>
<beans:bean id="integrationConversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<beans:property name="converters">
<beans:bean class="conversion.StringToFooConverter"/>
</beans:property>
</beans:bean>
在评估 SpEL 表达式期间,“integrationConversionService”起着重要的作用。每个表达式都针对一个 EvaluationContext 进行评估,并且该上下文知道“integrationConversionService”。在 Spring Integration 中,我们依赖 SpEL 进行所有方法调用(不仅在使用“expression”属性时,甚至对于“ref”和“method”配置也是如此)。这意味着您可以利用运行时类型转换将值从 Message 实例绑定到方法调用。例如,如果您正在调用 FooService 但在 Message 载荷中传递了一个 Bar 对象,那么您只需要将 BarToFooConverter 注册到“integrationConversionService”即可。这个示例还展示了一种更简洁的方式来注册 Converter。通过使用新的“converter”元素进行命名空间支持,您甚至不需要显式定义“integrationConversionService” bean
<!-- FooService.process(Foo) will be invoked, even though the Message payload is a Bar instance -->
<service-activator input-channel="in" ref="fooService" method="process" output-channel="out"/>
<converter>
<beans:bean class="example.BarToFooConverter"/>
</converter>
Spring Integration 1.0 有其自己的 TaskScheduler 实现,以及基于间隔和 cron 的 Trigger 实现。现在 Spring 3.0 提供了 TaskScheduler 和 Trigger,我们可以依赖这些。事实上,我们能够从 Spring Integration 端删除大量代码,同时将其中一些代码贡献回底层框架(例如轻量级的 CronTrigger 实现)。任何 Polling Consumer 都可以通过显式的 <poller> 子元素进行配置(否则,它将依赖于单个默认的 poller 配置)。这些 poller 元素接受以下属性之一:“fixed-delay”、“fixed-rate”或“cron”。实际上,您甚至可以提供 Spring 的 Trigger 接口的自定义实现,然后使用“trigger”属性作为引用。这里是带有 cron 表达式的 poller 示例
<file:inbound-channel-adapter directory="/some/path">
<poller cron="*/10 * 9-17 * * MON-FRI"/>
</file:inbound-channel-adapter>
我们的出站 HTTP 适配器现在委托给 Spring 的 RestTemplate 来执行 HTTP 请求和处理其响应。这意味着 HttpMessageConverter 策略起着核心作用。我们默认启用了几种转换器,但您可以完全自定义列表或添加自己的实现。实际上,我们在 HTTP 入站适配器中也使用了相同的 HttpMessageConverter 策略。另一个利用 RestTemplate 的不错特性是使用 URI 占位符。以下是一个 HTTP 出站 Messaging Gateway 的示例,它展示了自定义 HttpMessageConverter 和 URI 占位符的使用。实际上,URI 中被替换的值是 SpEL 在运行时对 Message 载荷进行评估的结果
<http:outbound-gateway id="trafficService"
url="http://example/traffic/{zipCode}"
request-channel="requestChannel"
reply-channel="responseChannel"
http-method="GET"
message-converters="trafficConverter"
expected-response-type="example.Traffic">
<http:uri-variable name="zipCode" expression="payload.address.zipcode"/>
</http:outbound-gateway>
在 2.0 版本中,我们还增加了对 Hohpe 和 Woolf 的企业集成模式一书中描述的更多模式的支持。
通过在 Application Context 中启用消息历史,每个 Message 都将添加一个头。该头会记录所有遍历过的组件,包括每个通道和端点的名称以及遍历的时间戳。对于异步交互和可能跨越多个线程的流很常见的消息应用程序,监控和审计可能是一个主要挑战。即使只在开发时启用,这个简单的头对于解决这个挑战也极其有用。切换这个特性很简单;只需在配置中添加或删除 <message-history> 元素即可。默认情况下,它会跟踪每个通道和端点的历史,但这可以通过简单的名称模式进行微调
<message-history tracked-components="*Service, foo*"/>
消息存储提供了一种方法来持久化消息,用于任何可能需要太长时间才能在单个事务中完成的过程。例如,通过使用新的基于 MessageStore 的消息通道,您可以拥有缓冲功能
<aggregator input-channel="in" ref="aggregator"
message-store="messageStore" output-channel="out"/>
<int-jdbc:message-store id="messageStore" data-source="dataSource"/>
保管条模式背后的想法是,您可以将消息载荷换成“保管条”,反之亦然。这允许您在跨通道发送消息时减少带宽和/或避免潜在的安全问题。您可以将其视为“按引用传递”,而不是典型的“按值传递”语义。我们的实现直接构建在我们刚才提到的消息存储支持之上。一对“claim-check-in”和“claim-check-out”转换器应该共享对同一个消息存储的引用。为了方便起见,首先会考虑一个名为“messageStore”的单个 bean。如果需要,您可以通过“message-store”属性提供一个显式引用。
<claim-check-in input-channel="payloadsIn" output-channel="ticketsOut"/>
<claim-check-out input-channel="ticketsIn" output-channel="payloadsOut"/>
控制总线允许您使用消息传递来管理和监控端点和通道。事实上,这是一个相当通用的机制,您可以在其中发送一条消息,该消息的载荷实际上是一个 SpEL 表达式,用于对集成应用程序中的某个组件进行评估。例如,您可以向控制总线的输入通道发送载荷为“@somePoller.stop()”的消息。为了启用此功能,只需添加元素
<control-bus input-channel="controlChannel"/>
我们在 Spring Integration 2.0 中添加了几个新的通道适配器和消息网关。这里不再提供每个示例配置,对于那些文档中已经很好地涵盖的,我将简单地提供 Spring Integration 参考手册中相关部分的链接。
还有一些其他的将在 GA 参考手册中介绍,但我也将在这里提供简要描述和/或相关链接。FTP 和 SFTP 适配器在 Josh Long 最近的这篇博客中有详细介绍。
我们还添加了 RSS/Atom Feed 读取支持。这里是一个示例
<feed:inbound-channel-adapter channel="newsChannel" url="http://example/news/rss.xml"/>
还有大家最喜欢的:Twitter 适配器。我们支持入站和出站状态更新以及直接消息。这里是一个简单的示例。如您所见,它支持配置一个启用 OAuth 的 Twitter Connection 实例
<twitter:outbound-update-channel-adapter channel="tweets"
twitter-connection="twitterConnection"/>
<twitter:twitter-connection id="twitterConnection"
consumer-key="${twitter.oauth.consumerKey}"
consumer-secret="${twitter.oauth.consumerSecret}"
access-token="${twitter.oauth.accessToken}"
access-token-secret="${twitter.oauth.accessTokenSecret}"/>
与上面显示的 SpEL 示例一样,您实际上可以将 Groovy 脚本用于任何 transformer、filter、router、splitter 等。这些脚本可以非常简单,并且可以利用在运行时绑定到脚本执行上下文的“payload”和“headers”。例如,以下 Groovy 脚本可以定义为“LengthRouter.groovy”
return payload.length() > 100 ? 'long' : 'short'
然后,您可以从 router 元素(或任何其他核心元素类型)中引用它。您可以提供一个“refresh-check-delay”属性,以便脚本的更改可以在运行时被拾取
<router input-channel="strings">
<int-groovy:script location="example/LengthRouter.groovy" refresh-check-delay="10000"/>
</router>
当然,您可以在 Groovy 脚本中做更多的事情。总的来说,Groovy 脚本选项在 SpEL 和 POJO 之间提供了一个很好的中间地带。
这些对称转换器可以将载荷对象与 Map 相互转换,其中 Map 中的键可以通过 SpEL 持有“扁平”属性路径(例如 'customer.address.city')。
<object-to-map-transformer input-channel="objectsIn" output-channel="mapsOut"/>
<map-to-object-transformer input-channel="mapsIn" output-channel="objectsOut"/>
这些对称转换器可以将载荷对象与 JSON 相互转换。它们使用 Jackson 库,并且如果需要自定义行为,可以引用 'object-mapper'。
<object-to-json-transformer input-channel="objectsIn" output-channel="jsonOut"/>
<json-to-object-transformer input-channel="jsonIn" output-channel="objectsOut"/>
这些对称转换器可以将载荷对象与字节数组相互转换。虽然在 2.0 中并非全新,但这些转换器现在委托给一对新的策略接口。默认策略是标准的 Java 序列化。但是,您可以选择提供一个“serializer”(或用于反序列化转换器的“deserializer”)属性值来引用任何 Serializer(或 Deserializer)实现。这些是 Spring 3.0.5 中可用的新策略接口。这些相同的策略也用于 JDBC MessageStore 以及 TCP/UDP 适配器中。再次强调,随着 Spring Data 项目的发展,您将看到很多新的实现。
<payload-serializing-transformer input-channel="objectsIn" output-channel="bytesOut"
serializer="someCustomSerializer"/>
<payload-deserializing-transformer input-channel="bytesIn" output-channel="objectsOut"
deserializer="someCustomDeserializer">
最后,我只想指出的是,最新版本的 SpringSource Tool Suite 中包含了一个非常棒的 Spring Integration 新可视化编辑器。如果您还没有使用 STS 2.5.0,您真的应该现在下载它!以下是我们的“Cafe”示例在 STS 可视化编辑器中的截图:
对我来说,像往常一样,原本是“简短”的博客变成了一篇有点史诗般的文章。最棒的是,即使这个看似很长的特性列表也只是 Spring Integration 2.0 提供的功能中的冰山一角。请务必下载 RC1 试用一下。一如既往,我们非常期待社区反馈。我们希望您喜欢 RC1,并且通过您在论坛和问题跟踪器中的贡献,我们可以确保 2.0 GA 版本会更好。
谢谢! -Mark