此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Integration 6.3.4spring-doc.cn

此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Integration 6.3.4spring-doc.cn

服务激活器是将任何 Spring 管理的对象连接到 Importing 通道的端点类型,以便它可以扮演服务的角色。 如果服务生成输出,则它还可能连接到输出通道。 或者,输出生成服务可能位于处理管道或消息流的末尾,在这种情况下,可以使用入站消息的标头。 如果未定义输出通道,则这是默认行为。 与此处描述的大多数配置选项一样,相同的行为实际上适用于大多数其他组件。replyChannelspring-doc.cn

服务激活器本质上是一个通用端点,用于使用输入消息(payload 和 headers)在某个对象上调用方法。 它的内部逻辑基于 a 可以是特定用例的任何可能实现,例如 、 、 等。 因此,本参考手册中提到的任何出站网关和出站通道适配器都应被视为此服务激活器终端节点的特定扩展;最后,它们都调用了某个对象的方法。MessageHandlerDefaultMessageSplitterAggregatingMessageHandlerSftpMessageHandlerJpaOutboundGatewayspring-doc.cn

配置 Service Activator

使用Java和注释配置,只需用注释标记相应的服务方法就足够了 - 当消息从输入通道消费时,框架会调用它:@ServiceActivatorspring-doc.cn

public class SomeService {

    @ServiceActivator(inputChannel = "exampleChannel")
    public void exampleHandler(SomeData payload) {
        ...
    }

}

有关更多信息,请参阅注释支持spring-doc.cn

对于 Java、Groovy 或 Kotlin DSL,an 的运算符表示服务激活器:.handle()IntegrationFlowspring-doc.cn

@Bean
public IntegrationFlow someFlow() {
    return IntegrationFlow
             .from("exampleChannel")
             .handle(someService, "exampleHandler")
             .get();
}
@Bean
fun someFlow() =
    integrationFlow("exampleChannel") {
        handle(someService, "exampleHandler")
    }
@Bean
someFlow() {
    integrationFlow 'exampleChannel',
            {
                handle someService, 'exampleHandler'
            }
}

有关这些 DSL 的更多信息,请参阅相应的章节:spring-doc.cn

要在使用 XML 配置时创建服务激活器,请使用带有 'input-channel' 和 'ref' 属性的 'service-activator' 元素,如下例所示:spring-doc.cn

<int:service-activator input-channel="exampleChannel" ref="exampleHandler"/>

前面的配置从 中选择满足消息收发要求之一的所有方法,如下所示:exampleHandlerspring-doc.cn

在运行时调用的目标方法按请求消息的类型为每条请求消息选择,或者作为类型的回退(如果目标类中存在此类方法)。payloadMessage<?>spring-doc.cn

从版本 5.0 开始,对于所有不匹配的情况,可以将一个服务方法标记为 作为回退。 当使用内容类型转换时,这在转换后调用目标方法时非常有用。@org.springframework.integration.annotation.Defaultspring-doc.cn

要委托给任何对象的显式定义方法,您可以添加该属性,如下例所示:methodspring-doc.cn

<int:service-activator input-channel="exampleChannel" ref="somePojo" method="someMethod"/>

在任一情况下,当 service 方法返回非 null 值时,终端节点都会尝试将回复消息发送到相应的回复通道。 要确定回复通道,它首先检查端点配置中是否提供了 an,如下例所示:output-channelspring-doc.cn

<int:service-activator input-channel="exampleChannel" output-channel="replyChannel"
                       ref="somePojo" method="someMethod"/>

如果该方法返回 result 且未定义 no,则框架将检查请求消息的标头值。 如果该值可用,则它会检查其类型。 如果是 ,则回复消息将发送到该通道。 如果它是 ,则端点会尝试将通道名称解析为通道实例。 如果无法解析通道,则抛出 a。 如果可以解决,则消息将发送到那里。 如果请求消息没有标头,并且对象是 a ,则查询其标头以获取目标目标。 这是 Spring Integration 中用于请求-回复消息传递的技术,它也是返回地址模式的一个例子。output-channelreplyChannelMessageChannelStringDestinationResolutionExceptionreplyChannelreplyMessagereplyChannelspring-doc.cn

如果您的方法返回结果,并且您希望丢弃该结果并结束流,则应将 配置为发送到 。 为方便起见,框架注册了一个名称为 . 有关更多信息,请参阅 特殊通道output-channelNullChannelnullChannelspring-doc.cn

服务激活器是生成回复消息不需要的组件之一。 如果您的方法返回或具有返回类型,则服务激活器将在方法调用后退出,没有任何信号。 此行为可由选项控制,该选项也与使用 XML 命名空间进行配置时一样公开。 如果 flag 设置为 且方法返回 null,则引发 a。nullvoidAbstractReplyProducingMessageHandler.requiresReplyrequires-replytrueReplyRequiredExceptionspring-doc.cn

service 方法中的参数可以是 message 或任意类型。 如果是后者,则假定它是消息有效负载,该有效负载从消息中提取并注入到服务方法中。 我们通常推荐这种方法,因为它在使用 Spring Integration 时遵循并促进了 POJO 模型。 参数也可以具有 or 注释,如 注释支持中所述。@Header@Headersspring-doc.cn

service 方法不需要具有任何参数,这意味着您可以实现事件样式的服务激活器(其中您只关心 service 方法的调用),而不必担心消息的内容。 将其视为 null JMS 消息。 此类实现的一个示例用例是 input 通道上存储的消息的简单计数器或监视器。

从版本 4.1 开始,框架将消息属性( 和 )正确转换为 Java 8 POJO 方法参数,如下例所示:payloadheadersOptionalspring-doc.cn

public class MyBean {
    public String computeValue(Optional<String> payload,
               @Header(value="foo", required=false) String foo1,
               @Header(value="foo") Optional<String> foo2) {
        if (payload.isPresent()) {
            String value = payload.get();
            ...
        }
        else {
           ...
       }
    }

}

如果自定义服务激活器处理程序实现可以在其他定义中重用,我们通常建议使用属性。 但是,如果自定义服务激活器处理程序实现仅在 的单个定义中使用,则可以提供内部 Bean 定义,如下例所示:ref<service-activator><service-activator>spring-doc.cn

<int:service-activator id="exampleServiceActivator" input-channel="inChannel"
            output-channel = "outChannel" method="someMethod">
    <beans:bean class="org.something.ExampleServiceActivator"/>
</int:service-activator>
不允许在同一配置中同时使用 attribute 和内部处理程序定义,因为它会创建不明确的条件并导致引发异常。ref<service-activator>
如果该属性引用了扩展的 bean(例如框架本身提供的处理程序),则通过将输出通道直接注入处理程序来优化配置。 在这种情况下,每个都必须是单独的 bean 实例(或-scoped bean)或使用内部配置类型。 如果您无意中从多个 bean 引用了相同的消息处理程序,则会收到配置异常。refAbstractMessageProducingHandlerrefprototype<bean/>

服务激活器和 Spring 表达式语言 (SpEL)

从 Spring Integration 2.0 开始,服务激活器也可以从 SPEL 中受益。spring-doc.cn

例如,你可以调用任何 Bean 方法,而无需在属性中指向 Bean 或将其作为内部 Bean 定义包括在内,如下所示:refspring-doc.cn

<int:service-activator input-channel="in" output-channel="out"
	expression="@accountService.processAccount(payload, headers.accountId)"/>

	<bean id="accountService" class="thing1.thing2.Account"/>

在前面的配置中,我们不是通过使用 or 作为内部 Bean 来注入“accountService”,而是使用 SpEL 的表示法并调用一个采用与消息有效负载兼容的类型的方法。 我们还传递一个 header 值。 任何有效的 SPEL 表达式都可以根据消息中的任何内容进行评估。 对于简单的场景,如果所有 logic 都可以封装在这样的表达式中,则您的服务激活器不需要引用 bean,如下例所示:ref@beanIdspring-doc.cn

<int:service-activator input-channel="in" output-channel="out" expression="payload * 2"/>

在前面的配置中,我们的服务逻辑是将 payload 值乘以 2。 SpEL 让我们相对容易地处理它。spring-doc.cn

有关配置服务激活器的更多信息,请参阅 Java DSL 一章中的服务激活器和 .handle() 方法spring-doc.cn

service 方法不需要具有任何参数,这意味着您可以实现事件样式的服务激活器(其中您只关心 service 方法的调用),而不必担心消息的内容。 将其视为 null JMS 消息。 此类实现的一个示例用例是 input 通道上存储的消息的简单计数器或监视器。
不允许在同一配置中同时使用 attribute 和内部处理程序定义,因为它会创建不明确的条件并导致引发异常。ref<service-activator>
如果该属性引用了扩展的 bean(例如框架本身提供的处理程序),则通过将输出通道直接注入处理程序来优化配置。 在这种情况下,每个都必须是单独的 bean 实例(或-scoped bean)或使用内部配置类型。 如果您无意中从多个 bean 引用了相同的消息处理程序,则会收到配置异常。refAbstractMessageProducingHandlerrefprototype<bean/>

异步服务激活器

服务激活器由调用线程调用。 如果输入通道是 a 或 的 poller 线程,则这是上游线程。 如果服务返回 ,则默认操作是将其作为发送到输出(或回复)通道的消息的有效负载发送。 从版本 4.3 开始,您现在可以将属性设置为 (通过使用 Java 配置)。 如果服务返回 when this the attribute is set to ,则会立即释放调用线程,并在完成 future 的线程(从您的服务内部)上发送回复消息。 这对于使用 的长时间运行的服务特别有利,因为 Poller 线程被释放以执行框架中的其他服务。SubscribableChannelPollableChannelCompletableFuture<?>asynctruesetAsync(true)CompletableFuture<?>asynctruePollableChannelspring-doc.cn

如果服务使用 完成 future ,则会发生正常的错误处理。 An 将发送到消息标头(如果存在)。 否则,将 an 发送到 default(如果可用)。ExceptionErrorMessageerrorChannelErrorMessageerrorChannelspring-doc.cn

从版本 6.1 开始,如果 的输出通道配置为 ,则默认情况下将打开异步模式。 如果处理程序结果不是反应式 type 或 ,则无论 output channel 类型如何,都会发生常规的回复生成过程。AbstractMessageProducingHandlerReactiveStreamsSubscribableChannelCompletableFuture<?>spring-doc.cn

有关更多信息,另请参阅 Reactive Streams Supportspring-doc.cn

Service Activator 和 Method 返回类型

service 方法可以返回任何类型,这些类型将成为回复消息有效负载。 在这种情况下,将创建一个新对象,并复制请求消息中的所有标头。 对于大多数 Spring 集成实现,当交互基于 POJO 方法调用时,其工作方式相同。Message<?>MessageHandlerspring-doc.cn

也可以从该方法返回一个完整的对象。 但是,请记住,与 transformer 不同,对于 Service Activator,如果返回的消息中尚不存在 headers,则将通过从请求消息中复制 headers 来修改此消息。 因此,如果您的 method 参数是 a,并且您复制了服务方法中的一些(但不是全部)现有标头,则它们将重新出现在回复消息中。 从回复消息中删除 Headers 不是 Service Activator 的责任,遵循松散耦合的原则,最好在集成流中添加 a。 或者,可以使用 Transformer 代替 Service Activator,但在这种情况下,当返回 full 时,该方法完全负责消息,包括复制请求消息标头(如果需要)。 您必须确保必须保留重要的框架标头(例如 , ),如果存在。Message<?>Message<?>HeaderFilterMessage<?>replyChannelerrorChannelspring-doc.cn