此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Integration 6.3.1Spring中文文档

此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Integration 6.3.1Spring中文文档

Spring Integration 提供了 Spring 编程模型的扩展,以支持众所周知的企业集成模式。 它支持在基于 Spring 的应用程序中进行轻量级消息传递,并支持通过声明性适配器与外部系统集成。 这些适配器提供了比 Spring 对远程处理、消息传递和调度的支持更高的抽象级别。Spring中文文档

Spring Integration 的主要目标是提供一个简单的模型来构建企业集成解决方案,同时保持关注点的分离,这对于生成可维护、可测试的代码至关重要。Spring中文文档

Spring 集成概述

本章简要介绍了 Spring Integration 的核心概念和组件。 它包括一些编程技巧,以帮助您充分利用 Spring Integration。Spring中文文档

背景

Spring 框架的关键主题之一是控制反转 (IoC)。 从广义上讲,这意味着框架代表在其上下文中管理的组件处理责任。 组件本身被简化,因为它们免除了这些责任。 例如,依赖关系注入减轻了组件查找或创建其依赖关系的责任。 同样,面向方面的编程通过将业务组件模块化为可重用的方面,减轻了业务组件的通用横切关注点。 在每种情况下,最终结果都是一个更易于测试、理解、维护和扩展的系统。Spring中文文档

此外,Spring 框架和产品组合为构建企业应用程序提供了一个全面的编程模型。 开发人员受益于此模型的一致性,尤其是它基于公认的最佳实践,例如对接口进行编程以及偏爱组合而不是继承。 Spring 简化的抽象和强大的支持库提高了开发人员的工作效率,同时提高了可测试性和可移植性的水平。Spring中文文档

Spring Integration 的动机是这些相同的目标和原则。 它将 Spring 编程模型扩展到消息传递领域,并建立在 Spring 现有的企业集成支持之上,以提供更高级别的抽象。 它支持消息驱动的体系结构,其中控制反转适用于运行时问题,例如某些业务逻辑应何时运行以及响应应发送到何处。 它支持消息的路由和转换,以便可以在不影响可测试性的情况下集成不同的传输和不同的数据格式。 换句话说,消息传递和集成问题由框架处理。 业务组件与基础架构进一步隔离,开发人员从复杂的集成责任中解脱出来。Spring中文文档

作为 Spring 编程模型的扩展,Spring Integration 提供了多种配置选项,包括注释、支持命名空间的 XML、具有通用“bean”元素的 XML 以及底层 API 的直接使用。 该 API 基于定义明确的策略接口和非侵入式委派适配器。 Spring Integration 的设计灵感来自于 Spring 中的常见模式与 Gregor Hohpe 和 Bobby Woolf (Addison Wesley, 2004) 的 Enterprise Integration Patterns 中描述的众所周知的模式之间的强烈亲和力。 读过这本书的开发人员应该会立即熟悉 Spring Integration 的概念和术语。Spring中文文档

目标和原则

Spring Integration 的动机是以下目标:Spring中文文档

Spring Integration 遵循以下原则:Spring中文文档

  • 组件应松散耦合,以实现模块化和可测试性。Spring中文文档

  • 该框架应强制将业务逻辑和集成逻辑之间的关注点分开。Spring中文文档

  • 扩展点在本质上应该是抽象的(但在明确定义的边界内),以促进重用和可移植性。Spring中文文档

主要部件

从垂直角度来看,分层架构有助于关注点的分离,而层间基于接口的契约促进了松耦合。 基于 Spring 的应用程序通常以这种方式设计,Spring 框架和产品组合为遵循企业应用程序全栈的这一最佳实践提供了坚实的基础。 消息驱动的架构增加了一个横向视角,但这些相同的目标仍然具有相关性。 正如“分层架构”是一种极其通用和抽象的范式一样,消息传递系统通常遵循类似抽象的“管道和过滤器”模型。 “过滤器”表示能够生成或使用消息的任何组件,“管道”在过滤器之间传输消息,以便组件本身保持松散耦合。 需要注意的是,这两种高级范式并不相互排斥。 支持“管道”的底层消息传递基础结构仍应封装在合约定义为接口的层中。 同样,“过滤器”本身应该在逻辑上高于应用程序服务层的层内进行管理,通过接口与这些服务进行交互,其方式与 Web 层大致相同。Spring中文文档

消息

在 Spring Integration 中,消息是任何 Java 对象的通用包装器,与框架在处理该对象时使用的元数据相结合。 它由有效负载和标头组成。 有效负载可以是任何类型,标头包含常用信息,例如 ID、时间戳、相关 ID 和返回地址。 标头还用于将值传递到连接的传输或从连接的传输传递值。 例如,从接收到的文件创建消息时,文件名可以存储在标头中,以便下游组件访问。 同样,如果邮件的内容最终将由出站邮件适配器发送,则上游组件可以将各种属性(to、from、cc、subject 等)配置为邮件头值。 开发人员还可以在标头中存储任意键值对。Spring中文文档

消息
图 1.消息

消息通道

消息通道表示管道和过滤器体系结构的“管道”。 生产者向频道发送消息,消费者从频道接收消息。 因此,消息通道将消息传递组件解耦,并为截获和监视消息提供了一个方便的点。Spring中文文档

消息通道
图2.消息通道

消息通道可以遵循点对点或发布-订阅语义。 使用点对点通道时,发送到通道的每条消息最多只能有一个使用者。 另一方面,发布-订阅频道尝试将每条消息广播给频道上的所有订阅者。 Spring Integration 支持这两种模型。Spring中文文档

虽然“点对点”和“发布-订阅”定义了最终接收每条消息的消费者数量的两个选项,但还有另一个重要的考虑因素:通道是否应该缓冲消息? 在Spring Integration中,可轮询通道能够在队列中缓冲消息。 缓冲的优点是它允许限制入站消息,从而防止使用者过载。 但是,顾名思义,这也增加了一些复杂性,因为只有在配置了轮询器的情况下,使用者才能从此类通道接收消息。 另一方面,连接到可订阅频道的消费者只是消息驱动的。消息通道实现详细讨论了 Spring Integration 中可用的各种通道实现。Spring中文文档

消息终结点

Spring Integration 的主要目标之一是通过控制权倒置来简化企业集成解决方案的开发。 这意味着您不必直接实现使用者和生产者,甚至不必在消息通道上构建消息并调用发送或接收操作。 相反,您应该能够通过基于纯对象的实现来专注于特定的域模型。 然后,通过提供声明性配置,您可以将特定于域的代码“连接”到 Spring Integration 提供的消息传递基础结构。 负责这些连接的组件是消息端点。 这并不意味着您必须直接连接现有的应用程序代码。 任何实际的企业集成解决方案都需要一定数量的代码,这些代码专注于集成问题,例如路由和转换。 重要的是实现集成逻辑和业务逻辑之间的关注点分离。 换言之,与 Web 应用程序的模型-视图-控制器 (MVC) 范例一样,目标应该是提供一个精简但专用的层,将入站请求转换为服务层调用,然后将服务层返回值转换为出站回复。 下一节概述了处理这些职责的消息端点类型,在接下来的章节中,您可以看到 Spring Integration 的声明性配置选项如何提供一种非侵入性的方式来使用其中的每一个。Spring中文文档

消息终结点

消息终结点表示管道和过滤器体系结构的“过滤器”。 如前所述,端点的主要作用是将应用程序代码连接到消息传递框架,并以非侵入性方式进行连接。 换言之,理想情况下,应用程序代码应该没有对消息对象或消息通道的感知。 这类似于 MVC 范式中控制器的角色。 正如控制器处理 HTTP 请求一样,消息端点处理消息。 正如控制器映射到 URL 模式一样,消息端点也映射到消息通道。 在这两种情况下,目标都是相同的:将应用程序代码与基础结构隔离开来。 《企业集成模式》一书中详细讨论了这些概念和后面的所有模式。 在这里,我们只提供 Spring Integration 支持的主要端点类型以及与这些类型关联的角色的高级描述。 后面的章节详细阐述并提供了示例代码和配置示例。Spring中文文档

消息转换器

消息转换器负责转换消息的内容或结构并返回修改后的消息。 可能最常见的转换器类型是将消息的有效负载从一种格式转换为另一种格式(例如从 XML 转换为 )。 同样,转换器可以添加、删除或修改消息的标头值。java.lang.StringSpring中文文档

消息过滤器

消息筛选器确定是否应将消息传递到输出通道。 这只需要一个布尔测试方法,该方法可以检查特定的有效负载内容类型、属性值、标头的存在或其他条件。 如果消息被接受,则将其发送到输出通道。 如果没有,它将被丢弃(或者,对于更严重的实现,可以抛出一个)。 邮件筛选器通常与发布-订阅通道结合使用,其中多个使用者可能会收到相同的消息,并使用筛选器的条件来缩小要处理的消息集。ExceptionSpring中文文档

请注意,不要将管道和过滤器体系结构模式中“筛选器”的通用用法与此特定终结点类型混淆,该终结点类型有选择地缩小两个通道之间流动的消息范围。 “过滤器”的管道和过滤器概念与Spring Integration的消息端点更接近:任何可以连接到消息通道以发送或接收消息的组件。

消息路由器

消息路由器负责决定接下来应接收消息的一个或多个通道(如果有)。 通常,决策基于消息的内容或消息标头中可用的元数据。 消息路由器通常用作服务激活器或其他能够发送应答消息的端点上静态配置的输出通道的动态替代方案。 同样,如前所述,消息路由器为多个订阅者使用的反应式消息过滤器提供了主动替代方案。Spring中文文档

路由器
图3.消息路由器

分配器

拆分器是另一种类型的消息端点,其职责是接受来自其输入通道的消息,将该消息拆分为多条消息,并将每条消息发送到其输出通道。 这通常用于将“复合”有效负载对象划分为包含细分有效负载的一组消息。Spring中文文档

聚合

聚合器基本上是拆分器的镜像,是一种消息端点,它接收多条消息并将它们组合成一条消息。 事实上,聚合器通常是包含拆分器的管道中的下游消费者。 从技术上讲,聚合器比拆分器更复杂,因为它需要维护状态(要聚合的消息),决定完整的消息组何时可用,并在必要时超时。 此外,在超时的情况下,聚合器需要知道是发送部分结果、丢弃部分结果还是将它们发送到单独的通道。 Spring Integration 提供了 、 和 可配置的超时设置,无论 在超时时发送部分结果,并发送丢弃通道。CorrelationStrategyReleaseStrategySpring中文文档

服务激活器

Service Activator 是用于将服务实例连接到消息传递系统的通用端点。 必须配置输入消息通道,并且,如果要调用的服务方法能够返回值,则还可以提供输出消息通道。Spring中文文档

输出通道是可选的,因为每条消息还可以提供自己的“返回地址”标头。 此规则适用于所有使用者终结点。

服务激活器对某些服务对象调用操作来处理请求消息,提取请求消息的有效负载并进行转换(如果该方法不需要消息类型化参数)。 每当服务对象的方法返回值时,该返回值也会在必要时转换为回复消息(如果它还不是消息类型)。 该回复消息将发送到输出通道。 如果未配置输出通道,则回复将发送到消息的“返回地址”中指定的通道(如果可用)。Spring中文文档

请求-答复服务激活器端点将目标对象的方法连接到输入和输出消息通道。Spring中文文档

处理程序终结点
图4.服务激活器
如前所述,在消息频道中,频道可以是可轮询的,也可以是可订阅的。 在上图中,这由“时钟”符号、实心箭头(轮询)和虚线箭头(订阅)表示。

通道适配器

通道适配器是将消息通道连接到其他系统或传输的端点。 通道适配器可以是入站的,也可以是出站的。 通常,通道适配器在消息与从其他系统接收或发送到其他系统的任何对象或资源(文件、HTTP 请求、JMS 消息等)之间执行一些映射。 根据传输的不同,通道适配器还可以填充或提取消息标头值。 Spring Integration 提供了许多通道适配器,这些适配器将在后面的章节中介绍。Spring中文文档

源终结点
图5.入站通道适配器端点将源系统连接到 .MessageChannel
邮件源可以是可轮询的(例如,POP3)或邮件驱动的(例如,IMAP 空闲)。 在上图中,这由“时钟”符号、实心箭头(轮询)和虚线箭头(消息驱动)表示。
目标终结点
图6.出站通道适配器端点将 连接到目标系统。MessageChannel
如前所述,消息频道可以是可轮询的,也可以是可订阅的。 在上图中,这由“时钟”符号、实心箭头(轮询)和虚线箭头(订阅)表示。

端点 Bean 名称

使用端点(任何带有 )的端点由两个 Bean 组成,即使用者和消息处理程序。 使用者具有对消息处理程序的引用,并在消息到达时调用它。inputChannelSpring中文文档

请考虑以下 XML 示例:Spring中文文档

<int:service-activator id = "someService" ... />

在前面的示例中,Bean 名称如下所示:Spring中文文档

使用企业集成模式 (EIP) 批注时,名称取决于多个因素。 请考虑以下带注释的 POJO 示例:Spring中文文档

@Component
public class SomeComponent {

    @ServiceActivator(inputChannel = ...)
    public String someMethod(...) {
        ...
    }

}

在前面的示例中,Bean 名称如下所示:Spring中文文档

从 V5.0.4 开始,您可以使用批注修改这些名称,如以下示例所示:@EndpointIdSpring中文文档

@Component
public class SomeComponent {

    @EndpointId("someService")
    @ServiceActivator(inputChannel = ...)
    public String someMethod(...) {
        ...
    }

}

在前面的示例中,Bean 名称如下所示:Spring中文文档

创建由具有 XML 配置的属性创建的名称。 请考虑以下带注释的 Bean 示例:@EndpointIdidSpring中文文档

@Configuration
public class SomeConfiguration {

    @Bean
    @ServiceActivator(inputChannel = ...)
    public MessageHandler someHandler() {
        ...
    }

}

在前面的示例中,Bean 名称如下所示:Spring中文文档

从 V5.0.4 开始,您可以使用批注修改这些名称,如以下示例所示:@EndpointIdSpring中文文档

@Configuration
public class SomeConfiguration {

    @Bean("someService.handler")             (1)
    @EndpointId("someService")               (2)
    @ServiceActivator(inputChannel = ...)
    public MessageHandler someHandler() {
        ...
    }

}
1 Handler:(Bean 名称)someService.handler
2 使用者:(终结点 ID)someService

注解创建的名称由具有 XML 配置的属性创建,只要您使用追加到名称的约定即可。@EndpointIdid.handler@BeanSpring中文文档

在一种特殊情况下,创建了第三个 Bean:出于体系结构原因,如果 a 未定义 ,则框架将提供的 Bean 包装在 . 此包装器支持请求处理程序建议处理,并发出正常的“生成无回复”调试日志消息。 它的 Bean 名称是处理程序 Bean 名称加号(如果存在 — 否则,它是正常生成的处理程序名称)。MessageHandler@BeanAbstractReplyProducingMessageHandlerReplyProducingMessageHandlerWrapper.wrapper@EndpointIdSpring中文文档

同样,可轮询消息源创建两个 Bean,一个 (SPCA) 和一个 .SourcePollingChannelAdapterMessageSourceSpring中文文档

请考虑以下 XML 配置:Spring中文文档

<int:inbound-channel-adapter id = "someAdapter" ... />

给定前面的 XML 配置,Bean 名称如下所示:Spring中文文档

考虑以下 POJO 的 Java 配置来定义:@EndpointIdSpring中文文档

@EndpointId("someAdapter")
@InboundChannelAdapter(channel = "channel3", poller = @Poller(fixedDelay = "5000"))
public String pojoSource() {
    ...
}

给定前面的 Java 配置示例,Bean 名称如下:Spring中文文档

考虑以下 Bean 的 Java 配置来定义:@EndpointIDSpring中文文档

@Bean("someAdapter.source")
@EndpointId("someAdapter")
@InboundChannelAdapter(channel = "channel3", poller = @Poller(fixedDelay = "5000"))
public MessageSource<?> source() {
    return () -> {
        ...
    };
}

在前面的示例中,Bean 名称如下所示:Spring中文文档

配置和@EnableIntegration

在本文档中,您可以看到对 XML 命名空间支持的引用,用于在 Spring 集成流中声明元素。 此支持由一系列命名空间解析器提供,这些解析器生成适当的 Bean 定义以实现特定组件。 例如,许多端点由 Bean 和 bean 组成,其中注入了处理程序和输入通道名称。MessageHandlerConsumerEndpointFactoryBeanSpring中文文档

第一次遇到 Spring Integration 命名空间元素时,框架会自动声明许多用于支持运行时环境的 bean(任务调度程序、隐式通道创建器等)。Spring中文文档

V4.0 引入了注解,以允许注册 Spring Integration 基础架构 bean(参见 Javadoc)。 当仅使用 Java 配置时,需要此注释 - 例如,具有 Spring Boot 或 Spring Integration Messaging Annotation 支持以及没有 XML 集成配置的 Spring Integration Java DSL。@EnableIntegration

当您有一个没有 Spring Integration 组件的父上下文以及两个或多个使用 Spring Integration 的子上下文时,注释也很有用。 它允许这些公共组件在父上下文中仅声明一次。@EnableIntegrationSpring中文文档

注释将许多基础结构组件注册到应用程序上下文中。 具体而言,它:@EnableIntegrationSpring中文文档

  • 为轮询器、SpEL 函数等注册一些内置 bean,例如 and its 。errorChannelLoggingHandlertaskSchedulerjsonPathSpring中文文档

  • 添加多个实例以增强全局和默认集成环境。BeanFactoryPostProcessorBeanFactorySpring中文文档

  • 添加多个实例以增强或转换和包装特定 Bean 以进行集成。BeanPostProcessorSpring中文文档

  • 添加批注处理器以分析消息批注,并在应用程序上下文中注册这些批注的组件。Spring中文文档

注释还允许类路径扫描。 此注解的作用与标准 Spring Framework 注解类似,但它仅限于特定于 Spring Integration 的组件和注解,而标准 Spring Framework 组件扫描机制无法访问这些组件和注解。 有关示例,请参阅@MessagingGateway注释@IntegrationComponentScan@ComponentScanSpring中文文档

注解注册一个 bean,并为那些不带属性的注解配置 bean。 如果找到多个注释,则它们必须具有相同的默认通道值。 有关详细信息,请参阅使用@Publisher注释的注释驱动配置@EnablePublisherPublisherAnnotationBeanPostProcessordefault-publisher-channel@Publisherchannel@EnablePublisherSpring中文文档

引入了注释来标记用于全局信道拦截的 Bean。 此批注是 XML 元素的类似物(请参阅全局信道拦截器配置)。 批注可以放置在类级别(使用构造型批注)或类内的方法上。 无论哪种情况,Bean 都必须实现 .@GlobalChannelInterceptorChannelInterceptor<int:channel-interceptor>@GlobalChannelInterceptor@Component@Bean@ConfigurationChannelInterceptorSpring中文文档

从 V5.1 开始,全局通道拦截器适用于动态注册的通道,例如使用 Java DSL 或通过 Java DSL 初始化的 Bean。 以前,在刷新应用程序上下文后创建 Bean 时,不会应用拦截器。beanFactory.initializeBean()IntegrationFlowContextSpring中文文档

注释将 、 或 bean 标记为 的候选转换器。 此批注是 XML 元素的类似物(请参阅有效负载类型转换)。 可以在类级别(使用构造型批注)或类内的方法上放置批注。@IntegrationConverterConverterGenericConverterConverterFactoryintegrationConversionService<int:converter>@IntegrationConverter@Component@Bean@ConfigurationSpring中文文档

有关消息传递批注的更多信息,请参阅批注支持Spring中文文档

编程注意事项

您应该尽可能使用普通的旧 Java 对象 (POJO),并且仅在绝对必要时才在代码中公开框架。 有关更多信息,请参见 POJO 方法调用Spring中文文档

如果确实将框架公开给类,则需要考虑一些注意事项,尤其是在应用程序启动期间:Spring中文文档

  • 如果组件是 ,则通常不应在方法中使用 。 相反,存储引用并将此类使用推迟到上下文生命周期的后期。ApplicationContextAwareApplicationContextsetApplicationContext()Spring中文文档

  • 如果组件是 or 使用方法,请不要从这些初始化方法发送任何消息。 调用这些方法时,应用程序上下文尚未初始化,发送此类消息可能会失败。 如果需要在启动期间发送消息,请实现并等待 . 或者,实现 ,将 Bean 置于后期阶段,然后从该方法发送消息。InitializingBean@PostConstructApplicationListenerContextRefreshedEventSmartLifecyclestart()Spring中文文档

使用包装(例如,阴影)罐时的注意事项

Spring Integration 通过使用 Spring Framework 的机制来加载多个类来引导某些功能。 这包括罐子以及某些其他罐子,包括 和 . 此过程的信息存储在每个 jar 的文件中。SpringFactoriesIntegrationConfigurationInitializer-core-http-jmxMETA-INF/spring.factoriesSpring中文文档

一些开发人员更喜欢使用众所周知的工具(例如 Apache Maven Shade 插件)将他们的应用程序和所有依赖项重新打包到一个 jar 中。Spring中文文档

默认情况下,shade 插件在生成 shaded jar 时不会合并文件。spring.factoriesSpring中文文档

除了 之外,其他文件( 和 )用于 XML 配置。 这些文件也需要合并。spring.factoriesMETA-INFspring.handlersspring.schemasSpring中文文档

Spring Boot 的可执行 jar 机制采用了不同的方法,因为它嵌套了 jar,从而将每个文件保留在类路径上。 因此,对于 Spring Boot 应用程序,如果您使用其默认的可执行 jar 格式,则不需要更多内容。spring.factories

即使你不使用 Spring Boot,你仍然可以使用 Boot 提供的工具,通过为上述文件添加转换器来增强阴影插件。 以下示例显示了如何配置插件:Spring中文文档

例 1.pom.xml
...
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <configuration>
                <keepDependenciesWithProvidedScope>true</keepDependenciesWithProvidedScope>
                <createDependencyReducedPom>true</createDependencyReducedPom>
            </configuration>
            <dependencies>
                <dependency> (1)
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <version>${spring.boot.version}</version>
                </dependency>
            </dependencies>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <transformers> (2)
                            <transformer
                                implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                <resource>META-INF/spring.handlers</resource>
                            </transformer>
                            <transformer
                                implementation="org.springframework.boot.maven.PropertiesMergingResourceTransformer">
                                <resource>META-INF/spring.factories</resource>
                            </transformer>
                            <transformer
                                implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                <resource>META-INF/spring.schemas</resource>
                            </transformer>
                            <transformer
                                implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
                        </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
...

具体说来Spring中文文档

1 添加为依赖项。spring-boot-maven-plugin
2 配置变压器。

您可以为显式版本添加属性或使用显式版本。${spring.boot.version}Spring中文文档

编程技巧和窍门

本节介绍了一些充分利用 Spring Integration 的方法。Spring中文文档

XML 架构

使用 XML 配置时,为了避免出现错误的模式验证错误,您应该使用“Spring-aware”IDE,例如 Spring Tool Suite (STS)、带有 Spring IDE 插件的 Eclipse 或 IntelliJ IDEA。 这些 IDE 知道如何从类路径解析正确的 XML 架构(通过使用 jar 中的文件)。 将 STS 或 Eclipse 与插件一起使用时,必须在项目上启用。META-INF/spring.schemasSpring Project NatureSpring中文文档

出于兼容性原因,某些旧模块(版本 1.0 中存在的模块)在 Internet 上托管的架构是 1.0 版本。 如果 IDE 使用这些架构,则可能会看到 false 错误。Spring中文文档

这些联机架构中的每一个都有一个类似于以下内容的警告:Spring中文文档

此架构适用于 Spring Integration Core 的 1.0 版本。 我们无法将其更新到当前架构,因为这会破坏任何使用 1.0.3 或更低版本的应用程序。 对于后续版本,“未版本化”模式从类路径解析并从 jar 中获取。 请参考 GitHub:Spring中文文档

受影响的模块包括Spring中文文档

查找 Java 和 DSL 配置的类名

借助 XML 配置和 Spring Integration Namespace 支持,XML 解析器隐藏了目标 Bean 的声明和连接方式。 对于 Java 配置,了解目标最终用户应用程序的框架 API 非常重要。Spring中文文档

EIP 实现的一等公民是 、 和 (参见本章前面的主要组件)。 它们的实现(合同)是:MessageChannelEndpointSpring中文文档

前两个非常简单,可以理解如何实现、配置和使用。 最后一个值得更多关注Spring中文文档

它在整个 Spring 框架中被广泛用于不同的组件实现。 其主要实现方式是:AbstractEndpointSpring中文文档

当您使用消息传递注释或 Java DSL 时,您无需担心这些组件,因为框架会自动生成它们并带有适当的注释和实现。 手动生成组件时,应使用 帮助确定要基于提供的属性创建的目标使用者实现。BeanPostProcessorConsumerEndpointFactoryBeanAbstractEndpointinputChannelSpring中文文档

另一方面,代表框架中的另一个一等公民 - . 此接口的实现目标是处理端点从通道使用的消息。 Spring Integration 中的所有 EIP 组件都是实现(例如、、、等)。 目标协议出站适配器(、、 等)也是实现。 当您使用 Java 配置开发 Spring Integration 应用程序时,您应该查看 Spring Integration 模块以找到用于配置的适当实现。 例如,若要发送 XMPP 消息(请参阅 XMPP 支持),应配置如下内容:ConsumerEndpointFactoryBeanorg.springframework.messaging.MessageHandlerMessageHandlerAggregatingMessageHandlerMessageTransformingHandlerAbstractMessageSplitterFileWritingMessageHandlerHttpRequestExecutingMessageHandlerAbstractMqttMessageHandlerMessageHandlerMessageHandler@ServiceActivatorSpring中文文档

@Bean
@ServiceActivator(inputChannel = "input")
public MessageHandler sendChatMessageHandler(XMPPConnection xmppConnection) {
    ChatMessageSendingMessageHandler handler = new ChatMessageSendingMessageHandler(xmppConnection);

    DefaultXmppHeaderMapper xmppHeaderMapper = new DefaultXmppHeaderMapper();
    xmppHeaderMapper.setRequestHeaderNames("*");
    handler.setHeaderMapper(xmppHeaderMapper);

    return handler;
}

实现表示消息流的出站和处理部分。MessageHandlerSpring中文文档

入站消息流端有自己的组件,这些组件分为轮询和侦听行为。 侦听(消息驱动)组件很简单,通常只需要一个目标类实现即可准备好 生成消息。 侦听组件可以是单向实现(如 和 )或请求-答复实现(如 和 )。MessageProducerSupportAbstractMqttMessageDrivenChannelAdapterImapIdleChannelAdapterMessagingGatewaySupportAmqpInboundGatewayAbstractWebServiceInboundGatewaySpring中文文档

轮询入站终结点适用于不提供侦听器 API 或不用于 这种行为,包括任何基于文件的协议(如FTP)、任何数据库(RDBMS或NoSQL)等。Spring中文文档

这些入站终结点由两个组件组成:轮询器配置,用于定期启动轮询任务, 以及一个消息源类,用于从目标协议读取数据并为下游集成流生成消息。 轮询器配置的第一类是 . 这是另一种实现,但特别是对于轮询以启动集成流。 通常,对于消息传递注释或 Java DSL,您不必担心此类。 框架根据配置或 Java DSL 构建器规范为其生成一个 bean。SourcePollingChannelAdapterAbstractEndpoint@InboundChannelAdapterSpring中文文档

消息源组件对于目标应用程序开发更为重要,它们都实现了接口(例如,和 )。 考虑到这一点,我们使用 JDBC 从 RDBMS 表中读取数据的配置可能如下所示:MessageSourceMongoDbMessageSourceAbstractTwitterMessageSourceSpring中文文档

@Bean
@InboundChannelAdapter(value = "fooChannel", poller = @Poller(fixedDelay="5000"))
public MessageSource<?> storedProc(DataSource dataSource) {
    return new JdbcPollingChannelAdapter(dataSource, "SELECT * FROM foo where status = 0");
}

您可以在特定的 Spring Integration 模块(在大多数情况下,在相应的包中)找到目标协议所需的所有入站和出站类。 例如,适配器包括:spring-integration-websocketSpring中文文档

  • o.s.i.websocket.inbound.WebSocketInboundChannelAdapter:用于侦听套接字上的帧并将消息生成到通道。MessageProducerSupportSpring中文文档

  • o.s.i.websocket.outbound.WebSocketOutboundMessageHandler:将传入消息转换为相应帧并通过 websocket 发送的单向实现。AbstractMessageHandlerSpring中文文档

如果您熟悉 Spring Integration XML 配置,从 4.3 版开始,我们在 XSD 元素定义,说明哪些目标类用于声明适配器或网关的 Bean,如以下示例所示:Spring中文文档

<xsd:element name="outbound-async-gateway">
    <xsd:annotation>
		<xsd:documentation>
Configures a Consumer Endpoint for the 'o.s.i.amqp.outbound.AsyncAmqpOutboundGateway'
that will publish an AMQP Message to the provided Exchange and expect a reply Message.
The sending thread returns immediately; the reply is sent asynchronously; uses 'AsyncRabbitTemplate.sendAndReceive()'.
       </xsd:documentation>
	</xsd:annotation>

POJO 方法调用

编程注意事项中所述,我们建议使用 POJO 编程风格,如以下示例所示:Spring中文文档

@ServiceActivator
public String myService(String payload) { ... }

在这种情况下,框架会提取有效负载,调用您的方法,并将结果包装在一条消息中,以发送到流中的下一个组件(原始标头将复制到新消息中)。 事实上,如果使用 XML 配置,甚至不需要注释,如以下配对示例所示:String@ServiceActivatorSpring中文文档

<int:service-activator ... ref="myPojo" method="myService" />
public String myService(String payload) { ... }

只要类上的公共方法中没有歧义,就可以省略该属性。methodSpring中文文档

还可以在 POJO 方法中获取标头信息,如以下示例所示:Spring中文文档

@ServiceActivator
public String myService(@Payload String payload, @Header("foo") String fooHeader) { ... }

还可以取消引用邮件的属性,如以下示例所示:Spring中文文档

@ServiceActivator
public String myService(@Payload("payload.foo") String foo, @Header("bar.baz") String barbaz) { ... }

由于可以使用各种 POJO 方法调用,因此 5.0 之前的版本使用 SpEL(Spring 表达式语言)来调用 POJO 方法。 与通常在方法中完成的实际工作相比,SpEL(甚至解释)对于这些操作通常“足够快”。 但是,从版本 5.0 开始,默认情况下会尽可能使用 。 这种技术通常比解释型 SpEL 执行得更快,并且与其他 Spring 消息传递项目一致。 这类似于用于在 Spring MVC 中调用控制器方法的技术。 使用 SpEL 时,仍会调用某些方法。 示例包括具有取消引用属性的带注释的参数,如前所述。 这是因为 SpEL 能够导航属性路径。org.springframework.messaging.handler.invocation.InvocableHandlerMethodInvocableHandlerMethodSpring中文文档

可能还有其他一些我们没有考虑过的极端情况也不适用于实例。 出于这个原因,在这些情况下,我们会自动回退到 SpEL。InvocableHandlerMethodSpring中文文档

如果需要,还可以设置 POJO 方法,使其始终使用 SpEL 和注释,如以下示例所示:UseSpelInvokerSpring中文文档

@UseSpelInvoker(compilerMode = "IMMEDIATE")
public void bar(String bar) { ... }

如果省略该属性,则 system 属性将确定编译器模式。 有关编译的 SpEL 的更多信息,请参阅 SpEL 编译compilerModespring.expression.compiler.modeSpring中文文档

请注意,不要将管道和过滤器体系结构模式中“筛选器”的通用用法与此特定终结点类型混淆,该终结点类型有选择地缩小两个通道之间流动的消息范围。 “过滤器”的管道和过滤器概念与Spring Integration的消息端点更接近:任何可以连接到消息通道以发送或接收消息的组件。
输出通道是可选的,因为每条消息还可以提供自己的“返回地址”标头。 此规则适用于所有使用者终结点。
如前所述,在消息频道中,频道可以是可轮询的,也可以是可订阅的。 在上图中,这由“时钟”符号、实心箭头(轮询)和虚线箭头(订阅)表示。
邮件源可以是可轮询的(例如,POP3)或邮件驱动的(例如,IMAP 空闲)。 在上图中,这由“时钟”符号、实心箭头(轮询)和虚线箭头(消息驱动)表示。
如前所述,消息频道可以是可轮询的,也可以是可订阅的。 在上图中,这由“时钟”符号、实心箭头(轮询)和虚线箭头(订阅)表示。
1 Handler:(Bean 名称)someService.handler
2 使用者:(终结点 ID)someService
V4.0 引入了注解,以允许注册 Spring Integration 基础架构 bean(参见 Javadoc)。 当仅使用 Java 配置时,需要此注释 - 例如,具有 Spring Boot 或 Spring Integration Messaging Annotation 支持以及没有 XML 集成配置的 Spring Integration Java DSL。@EnableIntegration
Spring Boot 的可执行 jar 机制采用了不同的方法,因为它嵌套了 jar,从而将每个文件保留在类路径上。 因此,对于 Spring Boot 应用程序,如果您使用其默认的可执行 jar 格式,则不需要更多内容。spring.factories
1 添加为依赖项。spring-boot-maven-plugin
2 配置变压器。

此架构适用于 Spring Integration Core 的 1.0 版本。 我们无法将其更新到当前架构,因为这会破坏任何使用 1.0.3 或更低版本的应用程序。 对于后续版本,“未版本化”模式从类路径解析并从 jar 中获取。 请参考 GitHub:Spring中文文档