如需使用最新稳定版本,请使用 Spring Integration 7.0.4spring-doc.cadn.net.cn

通道适配器

频道适配器是一个消息端点,它允许将单一发送者或接收者连接到一个消息通道。 Spring Integration 提供了多种适配器以支持各种传输方式,例如 JMS、文件、HTTP、Web 服务、邮件等。 本参考指南后续章节将讨论每种适配器。 然而,本章专注于简单但灵活的方法调用频道适配器支持。 既有入站适配器也有出站适配器,并且每个适配器都可以通过核心命名空间提供的 XML 元素进行配置。 这些提供了方便的扩展 Spring Integration 的方式,只要您有一个可以作为源或目的地调用的方法即可。spring-doc.cadn.net.cn

配置入站通道适配器

一个inbound-channel-adapter元素(在Java配置中为SourcePollingChannelAdapter)可以调用任何Spring管理的对象的方法,并将非空返回值发送到MessageChannel,同时将方法的输出转换为Message。 当适配器的订阅激活时,轮询器会尝试从源接收消息。 轮询器根据提供的配置使用TaskScheduler进行调度。 要为单独的通道适配器配置轮询间隔或cron表达式,可以提供一个带有调度属性(如'fixed-rate'或'cron')的'poller'元素。 以下示例定义了两个inbound-channel-adapter实例:spring-doc.cadn.net.cn

@Bean
public IntegrationFlow source1() {
    return IntegrationFlow.from(() -> new GenericMessage<>(...),
                             e -> e.poller(p -> p.fixedRate(5000)))
                ...
                .get();
}

@Bean
public IntegrationFlow source2() {
    return IntegrationFlow.from(() -> new GenericMessage<>(...),
                             e -> e.poller(p -> p.cron("30 * 9-17 * * MON-FRI")))
                ...
                .get();
}
public class SourceService {

    @InboundChannelAdapter(channel = "channel1", poller = @Poller(fixedRate = "5000"))
    Object method1() {
        ...
    }

    @InboundChannelAdapter(channel = "channel2", poller = @Poller(cron = "30 * 9-17 * * MON-FRI"))
    Object method2() {
        ...
    }
}
@Bean
fun messageSourceFlow() =
    integrationFlow( { GenericMessage<>(...) },
                    { poller { it.fixedRate(5000) } }) {
        ...
    }
<int:inbound-channel-adapter ref="source1" method="method1" channel="channel1">
    <int:poller fixed-rate="5000"/>
</int:inbound-channel-adapter>

<int:inbound-channel-adapter ref="source2" method="method2" channel="channel2">
    <int:poller cron="30 * 9-17 * * MON-FRI"/>
</int:channel-adapter>
若未提供轮询器,则必须在上下文中注册一个默认的轮询器。 详见 Endpoint命名空间支持
轮询端点的默认触发器是一个 PeriodicTrigger 实例,具有 1 秒的固定延迟周期。
重要提示:轮询器配置

所有 inbound-channel-adapter 类型都由一个 SourcePollingChannelAdapter 支持,这意味着它们包含一个轮询配置(poller configuration),该配置根据在 MessageSource 中指定的配置来轮询它(即调用一个自定义方法以产生值作为 Message 载荷)。 以下示例展示了两个轮询器的配置:spring-doc.cadn.net.cn

<int:poller max-messages-per-poll="1" fixed-rate="1000"/>

<int:poller max-messages-per-poll="10" fixed-rate="1000"/>

在第一种配置中,轮询任务每轮调用一次,并且,在每次任务(轮询)期间,根据max-messages-per-poll属性值,该方法会被调用一次以产生消息。 在第二种配置中,轮询任务每轮调用10次或直到返回'null'为止,因此可能在每次轮询时生成多达十个消息,而每次轮询之间的时间间隔为一秒钟。 然而,如果配置看起来像下面的示例:spring-doc.cadn.net.cn

<int:poller fixed-rate="1000"/>

注意,这里没有指定max-messages-per-poll。 正如我们后续会覆盖的那样,在PollingConsumer(例如,service-activatorfilterrouter和其他)中的相同的轮询配置将为max-messages-per-poll分配默认值-1,这意味着“除非轮询方法返回null(可能是因为消息队列QueueChannel中没有更多的消息),否则持续执行轮询任务”,然后睡眠一秒。spring-doc.cadn.net.cn

然而,在SourcePollingChannelAdapter中,情况略有不同。 max-messages-per-poll的默认值为1,除非你显式地将其设置为负值(例如-1)。 这确保了轮询器能够响应生命周期事件(如启动和停止),并防止在实现自定义方法的MessageSource有可能永远不会返回null且恰好是非中断的情况下,导致无限循环的问题。spring-doc.cadn.net.cn

然而,如果您确定您的方法可以返回 null,并且需要为每次轮询查询所有可用的源,请将 max-messages-per-poll 显式设置为负值,如下例所示:spring-doc.cadn.net.cn

<int:poller max-messages-per-poll="-1" fixed-rate="1000"/>

自 5.5 版本起,max-messages-per-poll0 值具有特殊意义 - 完全跳过对 MessageSource.receive() 的调用,这可以被视为在稍后的时间通过控制总线将 maxMessagesPerPoll 更改为非零值时暂停此入站通道适配器。spring-doc.cadn.net.cn

从版本 6.2 开始,fixed-delayfixed-rate 可以配置为 ISO 8601 持续时间格式,例如 PT10SP1D 等。 此外,底层 PeriodicTriggerinitial-interval 也被暴露出来,其值格式与 fixed-delayfixed-rate 类似。spring-doc.cadn.net.cn

也参见全局默认轮询器以获取更多信息。spring-doc.cadn.net.cn

配置出站通道适配器

一个outbound-channel-adapter元素(对于Java配置来说是一个@ServiceActivator)可以连接一个MessageChannel,使其能够将接收到的消息通道中的消息内容作为参数调用任何POJO消费者方法。 下面的示例展示了如何定义出站频道适配器:spring-doc.cadn.net.cn

@Bean
public IntegrationFlow outboundChannelAdapterFlow(MyPojo myPojo) {
    return f -> f
             .handle(myPojo, "handle");
}
public class MyPojo {

    @ServiceActivator(channel = "channel1")
    void handle(Object payload) {
        ...
    }

}
@Bean
fun outboundChannelAdapterFlow(myPojo: MyPojo) =
    integrationFlow {
        handle(myPojo, "handle")
    }
<int:outbound-channel-adapter channel="channel1" ref="target" method="handle"/>

<beans:bean id="target" class="org.MyPojo"/>

如果正在适配的通道是 PollableChannel,则必须提供一个 poller 子元素(即 @ServiceActivator 上的 @Poller 子注解),如下例所示:spring-doc.cadn.net.cn

public class MyPojo {

    @ServiceActivator(channel = "channel1", poller = @Poller(fixedRate = "3000"))
    void handle(Object payload) {
        ...
    }

}
<int:outbound-channel-adapter channel="channel2" ref="target" method="handle">
    <int:poller fixed-rate="3000" />
</int:outbound-channel-adapter>

<beans:bean id="target" class="org.MyPojo"/>

您应该使用一个ref属性,如果POJO消费者实现可以在其他<outbound-channel-adapter>定义中重用。 然而,如果消费者实现仅被单个定义的<outbound-channel-adapter>引用,则可以将其定义为内部bean,如下例所示:spring-doc.cadn.net.cn

<int:outbound-channel-adapter channel="channel" method="handle">
    <beans:bean class="org.Foo"/>
</int:outbound-channel-adapter>
在同一<outbound-channel-adapter>配置中同时使用ref属性和内部处理器定义是不允许的,因为这会导致一个模糊的状态。 这样的配置会抛出一个异常。

任何频道适配器都可以不依赖于channel引用创建,在这种情况下,它会隐式地创建一个DirectChannel的实例。 创建的频道名称与id属性相匹配,该属性位于<inbound-channel-adapter><outbound-channel-adapter>元素中。 因此,如果未提供channel,则必须提供idspring-doc.cadn.net.cn

通道适配器表达式与脚本

类似于其他Spring Integration组件,<inbound-channel-adapter><outbound-channel-adapter>也提供了SpEL表达式评估的支持。
要使用SpEL,请在'expression'属性中提供表达式字符串,而不是使用用于对bean进行方法调用的'ref'和'method'属性。
当表达式被评估时,它遵循与方法调用相同的契约:对于<inbound-channel-adapter>中的表达式,只要评估结果不是空值,就会生成一条消息;而对于<outbound-channel-adapter>中的表达式,必须等同于一个返回void的方法调用。spring-doc.cadn.net.cn

Spring Integration 3.0 及以上版本中,一个 <int:inbound-channel-adapter/> 也可以配置为 SpEL <expression/>(甚至可以是 <script/>)的子元素,以满足比简单 'expression' 属性所能实现的更为复杂的场景。 如果通过使用 location 属性提供脚本作为 Resource,还可以设置 refresh-check-delay,这允许资源定期重新加载。 如果您希望在每次轮询时都检查脚本,就需要与轮询器的触发器协调设置,如下例所示:spring-doc.cadn.net.cn

<int:inbound-channel-adapter ref="source1" method="method1" channel="channel1">
    <int:poller max-messages-per-poll="1" fixed-delay="5000"/>
    <script:script lang="ruby" location="Foo.rb" refresh-check-delay="5000"/>
</int:inbound-channel-adapter>

有关使用 <expression/> 子元素时,另请参阅 ReloadableResourceBundleExpressionSource 上的 cacheSeconds 属性。 有关表达式的更多信息,请参阅 Spring 表达式语言 (SpEL)。 有关脚本,请参阅 Groovy 支持脚本支持spring-doc.cadn.net.cn

The <int:inbound-channel-adapter/> (SourcePollingChannelAdapter) 是一个端点,通过周期性触发来定期调用以从某些底层的 MessageSource 中拉取消息。

spring-doc.cadn.net.cn

在拉取时,由于没有消息对象,表达式和脚本无法访问根 Message,因此大多数其他消息 SpEL 表达式的 payload 或 headers 属性在这里不可用。spring-doc.cadn.net.cn

脚本可以生成并返回一个完整的 Message 对象,包含头部信息和负载数据,或者仅返回负载数据。框架会将这些数据添加到具有基本头部信息的消息中。spring-doc.cadn.net.cn