领先一步
VMware 提供培训和认证,以加速您的进步。
了解更多我们很高兴地宣布“贷款经纪人”参考实现的第一部分。 '贷款经纪人' 概念已成为展示 企业集成模式 (EIP) 的事实上的参考领域 - 由 Gregor Hohpe 和 Bobby Woolf 撰写,而此“贷款经纪人”RI 的部分展示了如何使用 Spring Integration (SI) 框架实现和应用企业集成模式。
EIP 架构的核心是 管道和过滤器 和 消息 这两个非常简单但功能强大的概念。端点(过滤器)通过通道(管道)相互连接。生产端点将消息发送到通道,消息由消费端点检索。此架构旨在定义描述如何在端点之间交换信息的不同机制,而无需了解这些端点是什么或它们交换什么信息,从而提供了一种非常松散耦合且灵活的协作模型,同时还将集成问题与业务问题解耦。EIP 通过进一步定义扩展了此架构
Spring Integration (SI) 消息传递框架旨在提供基于 POJO 的编程模型,该模型构建在企业集成模式之上。
提交贷款报价请求 - 消息网关
消息网关模式提供了一种简单的机制来访问消息传递系统,包括我们的贷款经纪人。在 SI 中,您将网关定义为普通的 Java 接口(无需提供实现),通过 XML <gateway> 元素或通过注释进行配置,并将其用作任何其他 Spring Bean。SI 将负责通过生成消息(有效负载映射到方法的输入参数)并将其发送到指定的通道来委托和映射方法调用到消息传递基础设施。
LoanBrokerGateway.java 是消费者使用的消息网关的接口
网关 XML 配置
<int:gateway id="loanBrokerGateway"
default-request-channel="loanBrokerPreProcessingChannel"
service-interface="org.springframework.integration.loanbroker.LoanBrokerGateway"/>
在上述配置中,每当在“loanBrokerGateway”bean 上调用任何方法时,都会构建一条消息并将其发送到“loanBrokerPreProcessingChannel”。
我们对消息网关的定义(LoanBrokerGateway.java)为消费者提供了两种与贷款经纪人交互的方式。消费者可以通过调用getLoanQuote(loanRequest) 方法请求单个(最佳)报价,或通过调用getAllLoanQuotes(loanRequest) 方法请求所有报价。这意味着我们的贷款经纪人必须知道贷款请求的类型。我们还知道有一些预筛选步骤,例如获取和评估消费者的信用评分,因为某些顶级银行通常只会接受符合最低信用评分要求的消费者的报价请求。
从本质上讲,整个过程类似于看医生,在看真正的医生之前,你会先遇到护士,护士会测量你的体温、血压等,并写下医生需要的“元信息”列表。在 EIP 中,消息是一个简单的结构,它由消息有效负载和消息标头组成。消息标头是一种存储与消息相关的元信息的绝佳机制。那么我们如何用其他信息丰富我们的消息呢?EIP 定义了 内容丰富器 模式,该模式描述了如何使用其他信息增强消息。Spring Integration 提供了一个<header-enricher> 元素,允许您快速丰富传输中的消息。但是,由于我们的贷款经纪人必须在发送报价之前执行多个任务,因此如果有一种机制可以从一组独立的任务中组合一个过程,那将是很好的。
组合消息处理器模式描述了构建端点的规则,这些端点维护对由多个消息处理器组成的消息流的控制。在我们的案例中,预筛选流包括 3 个步骤:a) 确定贷款请求的类型; b) 获取消费者的信用记录和评分; c) 确定(根据某些条件)通道列表(每个通道对应一家独立的银行)。
Spring Integration 允许您通过<chain> 元素组合复杂的处理器
<int:chain id="preScreening" input-channel="loanBrokerPreProcessingChannel" output-channel="banksDistributionChannel">
<int:header-enricher>
<int:header name="RESPONSE_TYPE"
expression="headers.history.iterator().next().attributes['method'].equals('getLoanQuote') ? 'BEST' : 'ALL'" />
</int:header-enricher>
<int:header-enricher>
<int:header name="CREDIT_SCORE" ref="creditBureau" method="getCreditScore"/>
</int:header-enricher>
<int:header-enricher>
<int:header name="BANKS" ref="bankSelector" method="selectBankChannels"/>
</int:header-enricher>
</int:chain>
这将创建一个名为“preScreening”的 bean 作为 SI 链端点,该端点还定义了一个输入/输出通道以接收和发送消息。上述链由 3 个header-enricher处理器组成。第一个处理器将通过利用 SpEL 访问 消息历史记录 并根据调用的网关方法确定此标头的值来设置RESPONSE_TYPE标头。
此示例说明了如何使用 SpEL 执行简单的评估以确定标头值,但我们不建议使用 SpEL 执行复杂的业务逻辑接下来,我们有一个header-enricher,它映射到一个负责从信用局(当前存根 CreditBureauStub)获取信用评分并设置CREDIT_SCORE标头的过程。最后一个header-enricher使用 BankChannelSelector(参见 bankSelector 配置)。BankChannelSelector.selectBankChannels(..) 方法的实现将消息作为输入,并返回一个包含通道名称的 Set<String> 值,该值将设置为BANKS标头。这完成了我们的预筛选过程,我们的贷款经纪人现在已准备好通过banksDistributionChannel向每家选定的银行发送贷款请求。
BANKS标头定义了动态生成和过滤的通道列表,每个通道充当代表银行的接收者。我们需要一个端点,允许我们将相同的消息发送到所有接收者。
将贷款报价请求分发给选定的银行 - 收件人列表
EIP 定义了各种类型的路由模式,它们都派生自 消息路由器。其中之一是 收件人列表 路由器,它将消息路由到列表中的所有收件人。SI 提供了一个 <router> 元素,允许我们配置一个路由器,在本例中,它将从 bankDistributionChannel 接收 消息。此路由器将通过 SpEL 表达式从 BANKS 消息头 获取银行渠道列表(此列表在预筛选步骤中设置),并将 消息 分发到这些 渠道。下面的 XML 配置显示了此路由器的配置方式
<int:router id="bankRecipientListRouter" input-channel="banksDistributionChannel"
expression="headers['BANKS']"
apply-sequence="true"/>
您可以清楚地看到我们是如何通过通道(管道)连接各种端点(过滤器)来组装贷款经纪人的,同时传递消息。您还可以看到,我们通过基于 POJO 的编程技术实现了这一点,几乎没有使用 Spring Integration API(仅 BankChannelSelector.java)。SI 负责将我们的 POJO 与消息基础设施连接。贷款经纪人需要做的最后一件事是从银行接收贷款报价,按消费者汇总(我们不想向另一个消费者显示一个消费者的报价),根据消费者的选择标准(最佳报价或所有报价)组装响应,并回复给消费者。
汇总贷款报价响应 - 聚合器
聚合器模式描述了一个端点,该端点将相关的 消息 分组到单个 消息 中。可以提供标准和规则来确定 聚合 和 关联 策略。SI 提供了聚合器模式的几种实现以及方便的基于名称空间的配置。
我们的贷款经纪人通过 <aggregator> 元素定义了一个 'loanQuoteAggregator' bean,它提供了一个默认的 聚合器 和 关联 策略。默认的关联策略根据 $corelationId 头关联消息(请参阅 关联标识符 模式)。有趣的是,我们从未为该标头提供值。它是在之前由收件人列表路由器自动设置的,当时它为每个银行生成了一个单独的消息。
一旦消息相关联,它们就会被释放到实际的聚合器实现中。虽然 SI 提供了默认的聚合器,但其策略(收集所有消息的有效负载列表并使用此列表作为有效负载构造新消息)不满足我们的要求。原因是我们的消费者可能需要单个最佳报价或所有报价。为了传达消费者的请求,在流程的早期,我们设置了 RESPONSE_TYPE 标头。现在我们必须评估此标头并返回 所有报价(默认聚合策略将起作用)或 最佳报价(默认聚合策略将不起作用,因为我们必须确定哪个贷款报价是最好的)。
<int:aggregator id="loanQuoteAggregator" input-channel="quotesAggregationChannel" method="aggregateQuotes">
<bean class="org.springframework.integration.loanbroker.LoanQuoteAggregator"/>
</int:aggregator>
显然,选择最佳报价可以基于复杂的标准,并且会影响聚合器的复杂性,但目前我们将其简化。如果消费者想要最佳报价,我们将选择利率最低的报价。为了实现这一点,LoanQuoteAggregator.java 将对所有报价进行排序并返回第一个报价。LoanQuote.java 实现 Comparable,它根据 rate 属性比较报价。
创建响应消息后,它将发送到启动该流程的消息网关(因此是消费者)的 default-reply-channel。我们的消费者获得了贷款报价!
需要注意的一件重要事情是,我们没有在 <gateway> 元素上定义 default-reply-channel 属性。事实上,我们没有明确定义单个 channel。与其他消息系统类似,SI 会根据需要自动创建 输入 和默认的 回复 通道,从而为您提供另一种进一步简化 Spring 应用程序上下文配置的方法。
在下一期中,我们将演示 Spring Integration 中可用的各种远程适配器和技术,通过使用这些适配器替换我们的存根服务,并将介绍与“贷款经纪人”用例相关的异步集成风格。
资源:
“贷款经纪人”参考实现随 Spring Integration 2.0.M3 的发布一起提供(请参阅下载部分)。它作为独立的 Eclipse/Maven 项目分发。您也可以从我们的 Subversion 存储库中检出它作为项目。
$> svn co https://src.springframework.org/svn/spring-integration/trunk/spring-integration-samples/loan-broker/ loan-broker $> cd loan-broker $> mvn install
相关链接:Spring 集成 Spring 集成实战 企业集成模式 Spring 集成入门(Joshua Long) 敏捷 SOA - 第 1、2 和 3 部分(Tom McCuch)
感谢 Gary Russel (Spring Source,SI 贡献者) 和 Dave Turanski (Spring Source) 对此博客的帮助!