对于最新稳定版本,请使用 Spring Integration 7.0.0spring-doc.cadn.net.cn

Spring积分示例

自 Spring Integration 2.0 起,Spring Integration 分布不再包含这些样本。 相反,我们转向了更简单的协作模式,这应该促进更好的社区参与,理想情况下是更多的贡献。 样本现在有专门的 GitHub 仓库。 样本开发也有其自身的生命周期,不依赖于框架发布的生命周期,尽管仓库仍会为每个主要版本加上标签以保证兼容性。spring-doc.cadn.net.cn

对社区最大的好处是,我们现在可以添加更多采样,立即向你开放,无需等待下一次发布。 拥有自己的GitHub仓库,且不绑定在实际框架上,这也是很大的优势。 你现在有一个专门的地方可以建议 Samples,并报告现有样本的问题。 您也可以通过拉取请求向我们提交样本。 如果我们认为您的样本有价值,我们将非常乐意将其添加到“样本”库中,并正确注明您为作者。spring-doc.cadn.net.cn

Samples获取渠道

Spring 集成示例项目托管在 GitHub 上。 要查看或克隆这些样本,你必须在系统上安装一个Git客户端。 许多平台都有基于图形界面的产品(例如Eclipse IDE的EGit)。 简单的谷歌搜索可以帮助你找到它们。 你也可以用Git的命令行界面。spring-doc.cadn.net.cn

如果你需要更多关于如何安装或使用 Git 的信息,请访问:https://git-scm.com/

要通过 Git 命令行工具克隆(查看)Spring Integration 样本库,请执行以下命令:spring-doc.cadn.net.cn

$ git clone https://github.com/spring-projects/spring-integration-samples.git

前述命令将整个样本库克隆到名为Spring积分样本在你发布那个文件的工作目录里git命令。 由于样本库是一个实时仓库,你可能需要定期拉取(更新)来获取新的样本和现有样本的更新。 为此,请发行以下内容git pull命令:spring-doc.cadn.net.cn

$ git pull

提交样本或样本请求

你可以提交新的样本和样本请求。 我们非常感谢任何改进样本的努力,包括分享好点子。spring-doc.cadn.net.cn

我如何贡献自己的样本?

GitHub 是社交编码的:如果你想向 Spring 集成样本项目提交自己的代码示例,我们鼓励通过该仓库分支拉取请求进行贡献。 如果你想以这种方式贡献代码,请尽可能引用一个提供你样本细节的 GutHub issuespring-doc.cadn.net.cn

签署贡献者许可协议

非常重要:在接受您的Spring集成样本之前,您需要您签署SpringSource贡献者许可协议(CLA)。 签署贡献者协议并不意味着任何人拥有主仓库的权利,但这意味着我们可以接受你的贡献,并且如果我们这样做,你将获得作者署名。 如需阅读并签署CLA文件,请访问:spring-doc.cadn.net.cn

项目下拉菜单中,选择“春季集成”。 项目负责人是Artem Bilan。spring-doc.cadn.net.cn

代码贡献流程

关于实际的代码贡献过程,请阅读《Spring 集成贡献者指南》。 他们也申请了样本项目。 你可以在 github.com/spring-projects/spring-integration/blob/main/CONTRIBUTING.md 找到它们spring-doc.cadn.net.cn

这一流程确保每个提交都经过同行评审。 事实上,核心提交者遵循完全相同的规则。 我们非常期待您的春季集成 Samples!spring-doc.cadn.net.cn

示例请求

前所述,Spring 集成样本项目使用 GitHub issue 作为错误跟踪系统。 如需提交新的样本申请,请访问 github.com/spring-projects/spring-integration-samples/issuesspring-doc.cadn.net.cn

样本结构

从 Spring Integration 2.0 开始,样本的结构发生了变化。 随着计划收集更多样本,我们意识到并非所有样本的目标都相同。 它们的共同目标是教你如何应用和使用Spring Integration框架。 然而,它们的不同之处在于,有些样本侧重于技术用例,而另一些则侧重于业务用例。 此外,有些示例展示了可用于应对特定场景(包括技术和业务)的各种技术。 新的样本分类让我们能够更好地根据每个样本所涉及的问题进行组织,同时为你提供更简单的方式来找到适合你需求的样本。spring-doc.cadn.net.cn

目前分为四个类别。 在样本库中,每个类别都有自己的目录,目录以类别名称命名:spring-doc.cadn.net.cn

基础(采样/基础)

这里是一个很好的起点。 这里的示例具有技术动机,展示了配置和代码的最低限度。 这些内容能帮助你快速入门,介绍Spring Integration的基本概念、API和配置,以及企业集成模式(EIP)。 例如,如果你想了解如何实现和布线服务激活器到消息通道,如何用消息网关作为消息交换的幌子,或者如何开始使用MAIL、TCP/UDP或其他模块,这里是找到好示例的合适地方。 归根结底是采样/基础是个很好的起点。spring-doc.cadn.net.cn

中级(样本/中间体)

该类别面向已经熟悉 Spring Integration 框架(超出初学阶段)但在解决切换到消息架构后可能遇到的高级技术问题时需要更多指导的开发者。 例如,如果你想了解如何在各种消息交换场景中处理错误,或者如何正确配置聚合器以应对某些消息无法送达聚合的情况,或者任何其他超出特定组件基本实现和配置、暴露“还有什么”类型的问题, 这里是寻找这类 Samples的最佳地点。spring-doc.cadn.net.cn

高级(采样/高级)

该类别面向那些非常熟悉 Spring Integration 框架,但希望通过使用 Spring Integration 的公开 API 来满足特定自定义需求的开发者。 例如,如果你想找一些示例,展示如何实现自定义通道或消费者(基于事件或轮询),或者你想弄清楚如何在 Spring Integration 的 Bean 解析器层级结构上实现自定义 Bean 解析器(比如实现自定义组件的命名空间和模式时), 这里是正确的地方。 这里你还可以找到有助于开发适配器的示例。 Spring Integration自带丰富的适配器库,让你能够通过Spring Integration消息框架连接远程系统。 不过,你可能需要与核心框架没有提供适配器的系统集成。 如果是这样,你可能会决定自己实现(请考虑贡献)。 该类别会包含示例,展示如何作。spring-doc.cadn.net.cn

应用(示例/应用)

该类别面向那些对消息驱动架构和EIP有良好理解,并且对Spring和Spring集成有高于平均水平理解的开发者和架构师,他们正在寻找能够解决特定业务问题的样本。 换句话说,本类别示例的重点是业务用例,以及如何通过消息驱动架构,特别是Spring集成来解决这些用例。 例如,如果您想了解如何通过Spring Integration实现和自动化贷款经纪人或旅行社流程,这里是寻找此类示例的正确场所。spring-doc.cadn.net.cn

Spring Integration 是一个由社区驱动的框架。 因此,社区参与非常重要。 这也包括样本。 如果你找不到想要的东西,请告诉我们!

Samples

目前,Spring Integration 包含了不少示例,你只能期待更多。 为了帮助你更好地浏览这些样本,每个样本都有自己的特点readme.txt该文件涵盖了样本的多个细节(例如,它处理了哪些EIP模式、试图解决的问题、如何运行样本以及其他细节)。 然而,某些样本需要更详细且有时以图形方式解释。 在本节中,您可以找到我们认为需要特别关注的样本详情。spring-doc.cadn.net.cn

贷款经纪人

本节介绍了春季集成示例中包含的贷款经纪人示例申请。 这个样本的灵感来自Gregor Hohpe和Bobby Woolf的著作《企业集成模式》中出现的一个样本。spring-doc.cadn.net.cn

下图展示了整个过程:spring-doc.cadn.net.cn

贷款经纪人EIP
图1。贷款经纪人示例

EIP架构的核心是非常简单却强大的管道、过滤器,当然还有消息的概念。 端点(过滤器)通过通道(管道)相互连接。 产生端点向信道发送消息,消耗端点获取消息。 该架构旨在定义各种机制,描述端点之间信息的交换方式,而无需知道端点是什么或交换了哪些信息。 因此,它提供了一个非常松散耦合且灵活的协作模式,同时将集成问题与业务事务脱钩。 EIP通过进一步定义该架构来扩展:spring-doc.cadn.net.cn

  • 管道类型(点对点信道、发布-订阅信道、信道适配器等)spring-doc.cadn.net.cn

  • 关于过滤器与管道协作的核心过滤器和模式(消息路由器、分路器和聚合器、各种消息转换模式等)spring-doc.cadn.net.cn

EIP书的第9章很好地描述了这一用例的细节和变体,但这里是简要总结:在寻找最佳贷款报价时,消费者会订阅贷款经纪人的服务,他们会处理以下细节:spring-doc.cadn.net.cn

获取贷款报价的实际过程通常要复杂一些。 然而,由于我们的目标是展示企业集成模式如何在 Spring Integration 中实现和实现,因此该用例已简化为仅聚焦于流程中的集成方面。 这并不是试图给你消费者理财建议。spring-doc.cadn.net.cn

通过聘请贷款经纪人,消费者可以被隔离开来了解经纪人的运营细节,每个经纪人的运营可能会相互推迟以保持竞争优势,因此无论我们组建和实施什么方案都必须灵活,以便任何变更都能快速且无痛地实施。spring-doc.cadn.net.cn

贷款经纪人样本实际上并不与任何“虚构”的银行或信用局交流。 这些服务都被取消了。

我们的目标是组装、协调并测试整个流程中的集成方面。 只有这样,我们才能开始思考如何将这些流程接线到真实服务上。 在那时,无论某个贷款经纪人与多少家银行合作,或使用何种通信媒介(如JMS、WS、TCP等)与这些银行通信,组装后的流程及其配置都不会改变。spring-doc.cadn.net.cn

设计

当你分析前面列出的六个需求时,你会发现它们都是集成问题。 例如,在消费者预筛选步骤中,我们需要收集关于消费者及其需求的更多信息,并用更多元信息丰富贷款申请。 然后我们需要筛选这些信息,以选择最合适的银行列表,依此类推。 丰富、过滤和选择都是EIP以模式形式定义解的集成问题。 Spring Integration 提供了这些模式的实现。spring-doc.cadn.net.cn

下图展示了消息网关的表示:spring-doc.cadn.net.cn

网关
图2。消息网关

消息网关模式提供了访问消息系统(包括贷款经纪人)的简单机制。 在 Spring Integration 中,你可以将网关定义为一个普通的 Java 接口(无需提供实现),用 XML 配置<网关>Java中带注释的元素,并像使用其他Spring Bean一样使用它。 Spring Integration 通过生成消息(有效载荷映射到方法的输入参数)并将其发送到指定通道,来负责将方法调用委托和映射到消息基础设施。 以下示例展示了如何使用XML定义此类网关:spring-doc.cadn.net.cn

<int:gateway id="loanBrokerGateway"
  default-request-channel="loanBrokerPreProcessingChannel"
  service-interface="org.springframework.integration.samples.loanbroker.LoanBrokerGateway">
  <int:method name="getBestLoanQuote">
    <int:header name="RESPONSE_TYPE" value="BEST"/>
  </int:method>
</int:gateway>

我们目前的网关提供了两种可调用的方法。 一个能返回最佳单一报价,另一个则返回所有报价。 在某种程度上,我们需要在下游知道来电者需要什么样的回复。 在消息架构中实现这一点的最佳方式,是用描述你意图的元数据丰富消息内容。 内容丰富剂就是解决这个问题的模式之一。 Spring Integration 为了方便,提供了一个单独的配置元素,用任意数据丰富消息头部(后文将详细说明) 然而,由于网关元素负责构建初始消息,包含用任意消息头丰富新创建消息的能力。 在我们的例子中,我们添加一个RESPONSE_TYPE首部,值为最好每当getBestQuote()方法被调用。 对于其他方法,我们不添加任何头部。 现在我们可以在下游检查是否存在这个头部。 根据其存在和价值,我们可以判断来电者想要哪种类型的回复。spring-doc.cadn.net.cn

基于用例,我们也知道需要进行一些预筛查步骤,比如获取和评估消费者的信用评分,因为一些顶级银行只接受符合最低信用评分要求的消费者的报价请求。 因此,如果在转发给银行之前,信息能被丰富,那将是件好事。 如果需要完成多个流程以提供此类元信息,将这些进程集中到一个单元中,那将更好。 在我们的用例中,我们需要确定信用评分,并根据信用评分和某种规则,选择一系列消息通道(银行渠道)发送报价请求。spring-doc.cadn.net.cn

组合消息处理器

组合消息处理器模式描述了构建端点以维持对消息流控制的规则,消息流由多个消息处理器组成。 在 Spring Integration 中,组合消息处理器模式由<链>元素。spring-doc.cadn.net.cn

下图显示了链状图案:spring-doc.cadn.net.cn

链
图3。链

上图显示,我们有一个内部头部富集元素的链,进一步丰富了消息内容CREDIT_SCORE以及价值(由拨打信用服务确定——一个简单的POJOSpring豆,名称为“creditBureau”)。 然后它会委派给消息路由器。spring-doc.cadn.net.cn

下图展示了消息路由器的模式:spring-doc.cadn.net.cn

银行路由器
图4。消息路由器

Spring Integration 提供了多种消息路由模式的实现。 在这种情况下,我们使用路由器,根据Spring Expression Language中的表达式评估信道列表,该表达式查看信用评分(在前一步确定),并从中选择信道列表地图带有身份证银行其值为总理二 次,基于信用评分的价值。 一旦选中了频道列表,消息就会被路由到这些频道。spring-doc.cadn.net.cn

最后,贷款经纪人需要收到银行的贷款报价,按消费者汇总(我们不想将报价从一个消费者到另一个消费者),根据消费者的选择标准(单一最佳报价或所有报价)整理回复,并将回复发送给消费者。spring-doc.cadn.net.cn

下图展示了消息聚合器的模式:spring-doc.cadn.net.cn

报价汇总器
图5。消息聚合器

聚合器模式描述了一个端点,将相关消息分组为单一消息。 可以提供标准和规则来确定聚合和相关策略。 Spring Integration 提供了多种聚合模式的实现以及便捷的基于命名空间的配置。spring-doc.cadn.net.cn

以下示例展示了如何定义聚合器:spring-doc.cadn.net.cn

<int:aggregator id="quotesAggregator"
      input-channel="quotesAggregationChannel"
      method="aggregateQuotes">
  <beans:bean class="org.springframework.integration.samples.loanbroker.LoanQuoteAggregator"/>
</int:aggregator>

我们的贷款经纪人定义了“报价聚合器”,其中<聚合器>元素,提供默认的聚合和相关策略。 默认的相关策略基于关联Id(参见EIP手册中的相关标识符模式)。 注意我们从未提供该头部的值。 路由器会提前自动设置,为每个银行通道生成独立消息。spring-doc.cadn.net.cn

消息一旦关联完成,就会被释放到实际的聚合器实现中。 尽管 Spring Integration 提供了一个默认聚合器,但其策略(从所有消息中收集有效载荷列表,并以此列表构建新消息)无法满足我们的需求。 信息中包含所有结果是个问题,因为我们的客户可能需要一个最佳报价或所有报价。 为了传达消费者的意图,在流程早期我们设置了RESPONSE_TYPE页眉。 现在我们必须评估这个头部,返回所有报价(默认汇总策略可行)或最佳报价(默认汇总策略不起作用,因为我们必须确定哪个贷款报价最好)。spring-doc.cadn.net.cn

在更现实的应用中,选择最佳报价可能基于复杂的标准,这些标准可能影响聚合器的实现和配置复杂度。 不过目前,我们让它变得简单。 如果消费者想要最优惠的报价,我们会选择利率最低的报价。 为了实现这一点,贷款报价聚合器Class会按利率排序所有报价,并返回第一个报价。 这贷款报价类实现可比较的根据费率属性比较报价。 一旦响应消息被创建,它会发送到消息网关的默认回复通道(也就是发送给发端的消费者)。 我们的客户拿到了贷款报价!spring-doc.cadn.net.cn

总之,基于POJO(即现有或遗留)逻辑和一个轻量级、可嵌入的消息框架(Spring Integration)构建了一个相当复杂的过程,该框架采用松耦合的编程模型,旨在简化异构系统的集成,而无需重型ESB类引擎或专有的开发与部署环境。 作为开发者,你不应该因为有集成问题就把你的Swing或基于控制台的应用移植到类似ESB的服务器,或者实现专有接口。spring-doc.cadn.net.cn

本节示例及其他示例均建立在企业集成模式之上。 你可以把它们看作是你解决方案的“构建模块”。 它们并非旨在成为完整的解决方案。 集成问题存在于所有类型的应用中(无论是基于服务器还是非服务器)。 我们的目标是让集成应用无需改变设计、测试和部署策略。spring-doc.cadn.net.cn

咖啡馆样本

本节介绍了包含在春季集成示例中的咖啡馆示例应用。 这个采样灵感来自Gregor Hohpe的《Ramblings》中另一个采样。spring-doc.cadn.net.cn

该领域是咖啡馆,下图展示了基本流程:spring-doc.cadn.net.cn

咖啡馆EIP
图6。咖啡馆 Samples

次序对象可以包含多个订单项. 下单后,分线器会将复合订单消息拆分为每杯饮料的一条消息。 然后,每一项都由路由器处理,通过检查订单项object的“isIced”属性)。 这咖啡师由准备每杯饮品,但热饮和冷饮的准备有两种截然不同的方法:“准备热饮”和“准备冷饮”。 准备好的饮品随后被送往服务员其中它们被聚合为交货对象。spring-doc.cadn.net.cn

以下列表展示了XML配置:spring-doc.cadn.net.cn

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:int="http://www.springframework.org/schema/integration"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:beans="http://www.springframework.org/schema/beans"
 xmlns:int-stream="http://www.springframework.org/schema/integration/stream"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
  https://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/integration
  https://www.springframework.org/schema/integration/spring-integration.xsd
  http://www.springframework.org/schema/integration/stream
  https://www.springframework.org/schema/integration/stream/spring-integration-stream.xsd">

    <int:gateway id="cafe" service-interface="o.s.i.samples.cafe.Cafe"/>

    <int:channel  id="orders"/>
    <int:splitter input-channel="orders" ref="orderSplitter"
                  method="split" output-channel="drinks"/>

    <int:channel id="drinks"/>
    <int:router  input-channel="drinks"
                 ref="drinkRouter" method="resolveOrderItemChannel"/>

    <int:channel id="coldDrinks"><int:queue capacity="10"/></int:channel>
    <int:service-activator input-channel="coldDrinks" ref="barista"
                           method="prepareColdDrink" output-channel="preparedDrinks"/>

    <int:channel id="hotDrinks"><int:queue capacity="10"/></int:channel>
    <int:service-activator input-channel="hotDrinks" ref="barista"
                           method="prepareHotDrink" output-channel="preparedDrinks"/>

    <int:channel id="preparedDrinks"/>
    <int:aggregator input-channel="preparedDrinks" ref="waiter"
                    method="prepareDelivery" output-channel="deliveries"/>

    <int-stream:stdout-channel-adapter id="deliveries"/>

    <beans:bean id="orderSplitter"
                class="org.springframework.integration.samples.cafe.xml.OrderSplitter"/>

    <beans:bean id="drinkRouter"
                class="org.springframework.integration.samples.cafe.xml.DrinkRouter"/>

    <beans:bean id="barista" class="o.s.i.samples.cafe.xml.Barista"/>
    <beans:bean id="waiter"  class="o.s.i.samples.cafe.xml.Waiter"/>

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

</beans:beans>

每个消息端点连接到输入通道、输出通道或两者。 每个端点管理自己的生命周期(默认情况下,端点在初始化后自动启动,为防止这种情况,添加自动启动属性,其值为false). 最重要的是,这些对象是带有强类型方法参数的简单POJO。 以下示例展示了分流器:spring-doc.cadn.net.cn

public class OrderSplitter {
    public List<OrderItem> split(Order order) {
        return order.getItems();
    }
}

对于路由器来说,返回值不必是消息频道实例(虽然,它也可以是)。 在这个例子中,一个字符串以下列表显示显示的是包含频道名称的值。spring-doc.cadn.net.cn

public class DrinkRouter {
    public String resolveOrderItemChannel(OrderItem orderItem) {
        return (orderItem.isIced()) ? "coldDrinks" : "hotDrinks";
    }
}

现在回到 XML 部分,你可以看到有两个<服务激活器>元素。 这些人都委派给同一个咖啡师但采用不同的方法(准备热饮准备冷饮),每个通道对应两个已路由订单项目的通道之一。 以下列表展示了咖啡师类别(其中包含准备热饮准备冷饮方法)spring-doc.cadn.net.cn

public class Barista {

    private long hotDrinkDelay = 5000;
    private long coldDrinkDelay = 1000;

    private AtomicInteger hotDrinkCounter = new AtomicInteger();
    private AtomicInteger coldDrinkCounter = new AtomicInteger();

    public void setHotDrinkDelay(long hotDrinkDelay) {
        this.hotDrinkDelay = hotDrinkDelay;
    }

    public void setColdDrinkDelay(long coldDrinkDelay) {
        this.coldDrinkDelay = coldDrinkDelay;
    }

    public Drink prepareHotDrink(OrderItem orderItem) {
        try {
            Thread.sleep(this.hotDrinkDelay);
            System.out.println(Thread.currentThread().getName()
                    + " prepared hot drink #" + hotDrinkCounter.incrementAndGet()
                    + " for order #" + orderItem.getOrder().getNumber()
                    + ": " + orderItem);
            return new Drink(orderItem.getOrder().getNumber(), orderItem.getDrinkType(),
                    orderItem.isIced(), orderItem.getShots());
        }
        catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return null;
        }
    }

    public Drink prepareColdDrink(OrderItem orderItem) {
        try {
            Thread.sleep(this.coldDrinkDelay);
            System.out.println(Thread.currentThread().getName()
                    + " prepared cold drink #" + coldDrinkCounter.incrementAndGet()
                    + " for order #" + orderItem.getOrder().getNumber() + ": "
                    + orderItem);
            return new Drink(orderItem.getOrder().getNumber(), orderItem.getDrinkType(),
                    orderItem.isIced(), orderItem.getShots());
        }
        catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return null;
        }
    }
}

正如你从前面代码摘录中看到的,咖啡师方法有不同的延迟(热饮准备时间是准备时间的五倍)。 这模拟了工作完成速度的不同。 当咖啡演示“主”方法运行,循环100次,每次发送一杯热饮和一杯冷饮。 它实际上是通过调用“placeOrder”方法发送消息的咖啡屋接口。 在早期的XML配置中,你可以看到<网关>元素被指定。 这会触发创建一个代理,实现该服务接口并将其连接到通道。 频道名称在@Gateway注释咖啡屋接口,正如以下接口定义所示:spring-doc.cadn.net.cn

public interface Cafe {

    @Gateway(requestChannel="orders")
    void placeOrder(Order order);

}

最后,看看main()方法咖啡演示本身:spring-doc.cadn.net.cn

public static void main(String[] args) {
    AbstractApplicationContext context = null;
    if (args.length > 0) {
        context = new FileSystemXmlApplicationContext(args);
    }
    else {
        context = new ClassPathXmlApplicationContext("cafeDemo.xml", CafeDemo.class);
    }
    Cafe cafe = context.getBean("cafe", Cafe.class);
    for (int i = 1; i <= 100; i++) {
        Order order = new Order(i);
        order.addItem(DrinkType.LATTE, 2, false);
        order.addItem(DrinkType.MOCHA, 3, true);
        cafe.placeOrder(order);
    }
}
要运行此样本及其他八个样本,请参阅README.txt Samples主发行版目录(如本章开头所述)。

当你奔跑时咖啡演示你可以看到冷饮最初的准备速度比热饮快。 由于有聚合器,冷饮的供应实际上受制于热饮的制作速度。 这在意料之中,因为它们分别延迟了1000毫秒和5000毫秒。 然而,通过配置带有并发任务执行器的轮询器,你可以显著改变结果。 例如,你可以用一个线程池执行者,配备五名员工,负责热饮咖啡师,同时保持冷饮咖啡师现状。 以下列表对此类安排进行了配置:spring-doc.cadn.net.cn

<int:service-activator input-channel="hotDrinks"
                     ref="barista"
                     method="prepareHotDrink"
                     output-channel="preparedDrinks"/>

  <int:service-activator input-channel="hotDrinks"
                     ref="barista"
                     method="prepareHotDrink"
                     output-channel="preparedDrinks">
      <int:poller task-executor="pool" fixed-rate="1000"/>
  </int:service-activator>

  <task:executor id="pool" pool-size="5"/>

另外,注意每次调用都会显示工人线程名称。 你可以看到热饮是由任务执行者线程准备的。 如果你提供更短的轮询器间隔(比如100毫秒),你会发现它偶尔会通过强制任务调度器(调用者)调用该作来限速输入。spring-doc.cadn.net.cn

除了试验轮询器的并发设置外,你还可以添加“事务”子元素,然后引用任意PlatformTransactionManager实例在语境中。

XML 消息示例

XML消息示例基本/XML展示了如何使用一些提供的组件,这些组件处理 XML 负载。 该示例采用了处理以XML表示的书籍订单的理念。spring-doc.cadn.net.cn

这个示例表明命名空间的前缀可以是你想要的任何前缀。 虽然我们通常使用,INT-XML对于集成的XML组件,示例中使用SI-XML. (智力是“积分”的缩写,且是“Spring Integration”的缩写。)

首先,订单被拆分为若干条消息,每条消息代表XPath分流器组件中的单个订单项。 以下列表展示了分线器的配置:spring-doc.cadn.net.cn

<si-xml:xpath-splitter id="orderItemSplitter" input-channel="ordersChannel"
              output-channel="stockCheckerChannel" create-documents="true">
      <si-xml:xpath-expression expression="/orderNs:order/orderNs:orderItem"
                                namespace-map="orderNamespaceMap" />
  </si-xml:xpath-splitter>

服务激活器随后将消息传递给库存检查POJO。 订单项目文档会根据库存检查器提供的关于订单物品库存水平的信息而丰富。 这个丰富订单项消息随后用于路由消息。 如果订单商品有库存,消息会被转发到仓库。 以下列表配置为xpath-router这会将消息路由:spring-doc.cadn.net.cn

<si-xml:xpath-router id="inStockRouter" input-channel="orderRoutingChannel" resolution-required="true">
    <si-xml:xpath-expression expression="/orderNs:orderItem/@in-stock" namespace-map="orderNamespaceMap" />
    <si-xml:mapping value="true" channel="warehouseDispatchChannel"/>
    <si-xml:mapping value="false" channel="outOfStockChannel"/>
</si-xml:xpath-router>

当订单商品缺货时,消息会用XSLT转换为适合发送给提供商的格式。 以下列表配置XSLT转换器:spring-doc.cadn.net.cn

<si-xml:xslt-transformer input-channel="outOfStockChannel"
  output-channel="resupplyOrderChannel"
  xsl-resource="classpath:org/springframework/integration/samples/xml/bigBooksSupplierTransformer.xsl"/>