凭证检查

在前面的章节中,我们介绍了几个内容丰富器组件,它们可以帮助你处理消息缺少数据的情况。我们还讨论了内容过滤,它允许你从消息中删除数据项。但是,有时我们希望暂时隐藏数据。例如,在分布式系统中,我们可能会收到包含非常大有效负载的消息。一些间歇性的消息处理步骤可能不需要访问此有效负载,而另一些步骤可能只需要访问某些头信息,因此在每个处理步骤中都携带大型消息有效负载可能会导致性能下降,可能会产生安全风险,并且可能会使调试更加困难。

存储在库中”(或认领凭证)模式描述了一种机制,它允许你将数据存储在众所周知的位置,同时只维护指向该数据位置的指针(认领凭证)。你可以将该指针作为新消息的有效负载传递,从而让消息流中的任何组件在需要时获取实际数据。这种方法与挂号邮件流程非常相似,你可以在邮箱中收到认领凭证,然后必须去邮局领取你的实际包裹。它也是航班或酒店行李领取的相同概念。

Spring 集成提供了两种类型的认领凭证转换器

  • 传入认领凭证转换器

  • 传出认领凭证转换器

方便的基于命名空间的机制可用于配置它们。

传入认领凭证转换器

传入认领凭证转换器通过将传入消息存储在其message-store属性标识的消息存储中来转换传入消息。以下示例定义了一个传入认领凭证转换器

<int:claim-check-in id="checkin"
        input-channel="checkinChannel"
        message-store="testMessageStore"
        output-channel="output"/>

在前面的配置中,接收到的input-channel上的消息将持久化到message-store属性标识的消息存储中,并使用生成的 ID 进行索引。该 ID 是该消息的认领凭证。认领凭证也成为发送到output-channel的新(转换后的)消息的有效负载。

现在,假设在某个时刻你需要访问实际消息。你可以手动访问消息存储并获取消息的内容,或者你可以使用相同的方法(创建转换器),只是现在你使用传出认领凭证转换器将认领凭证转换为实际消息。

以下列表概述了传入认领凭证转换器的所有可用参数

<int:claim-check-in auto-startup="true"             (1)
                    id=""                           (2)
                    input-channel=""                (3)
                    message-store="messageStore"    (4)
                    order=""                        (5)
                    output-channel=""               (6)
                    send-timeout="">                (7)
    <int:poller></int:poller>                       (8)
</int:claim-check-in>
1 生命周期属性,指示此组件是否应该在应用程序上下文启动期间启动。它默认为true。此属性在Chain元素内部不可用。可选。
2 标识底层 Bean 定义的 ID(MessageTransformingHandler)。此属性在 Chain 元素内不可用。可选。
3 此端点的接收消息通道。此属性在 Chain 元素内不可用。可选。
4 对将由此声明检查转换器使用的 MessageStore 的引用。如果未指定,则默认引用为名为 messageStore 的 Bean。可选。
5 指定当此端点作为订阅者连接到通道时调用的顺序。当该通道使用 failover 分派策略时,这尤其重要。当此端点本身是具有队列的通道的轮询消费者时,它没有效果。此属性在 Chain 元素内不可用。可选。
6 标识消息在由此端点处理后发送到的消息通道。此属性在 Chain 元素内不可用。可选。
7 指定将回复消息发送到输出通道时等待的最大时间量(以毫秒为单位)。默认为 30 秒。此属性在 Chain 元素内不可用。可选。
8 定义轮询器。此元素在 Chain 元素内不可用。可选。

传出声明检查转换器

传出声明检查转换器允许您将具有声明检查有效负载的消息转换为具有原始内容作为其有效负载的消息。

<int:claim-check-out id="checkout"
        input-channel="checkoutChannel"
        message-store="testMessageStore"
        output-channel="output"/>

在前面的配置中,接收到的 input-channel 上的消息应具有声明检查作为其有效负载。传出声明检查转换器通过查询消息存储以获取由提供的声明检查标识的消息,将其转换为具有原始有效负载的消息。然后,它将新签出的消息发送到 output-channel

以下列表概述了传出声明检查转换器的所有可用参数

<int:claim-check-out auto-startup="true"             (1)
                     id=""                           (2)
                     input-channel=""                (3)
                     message-store="messageStore"    (4)
                     order=""                        (5)
                     output-channel=""               (6)
                     remove-message="false"          (7)
                     send-timeout="">                (8)
    <int:poller></int:poller>                        (9)
</int:claim-check-out>
1 生命周期属性,指示此组件是否应该在应用程序上下文启动期间启动。它默认为true。此属性在Chain元素内部不可用。可选。
2 标识底层 Bean 定义的 ID(MessageTransformingHandler)。此属性在 Chain 元素内不可用。可选。
3 此端点的接收消息通道。此属性在 Chain 元素内不可用。可选。
4 对将由此声明检查转换器使用的 MessageStore 的引用。如果未指定,则默认引用为名为 messageStore 的 Bean。可选。
5 指定当此端点作为订阅者连接到通道时调用的顺序。当该通道使用 failover 分派策略时,这尤其重要。当此端点本身是具有队列的通道的轮询消费者时,它没有效果。此属性在 Chain 元素内不可用。可选。
6 标识消息在由此端点处理后发送到的消息通道。此属性在 Chain 元素内不可用。可选。
7 如果设置为 true,则此转换器将从 MessageStore 中删除消息。当消息只能“声明”一次时,此设置很有用。它默认为 false。可选。
8 指定向输出通道发送回复消息时等待的最大时间(以毫秒为单位)。默认值为30秒。此属性在Chain元素内部不可用。可选。
9 定义轮询器。此元素在 Chain 元素内不可用。可选。

仅领取一次

有时,特定消息必须仅领取一次。打个比方,考虑处理飞机行李的过程。您在出发时托运行李,并在到达时领取行李。行李一旦被领取,就不能再次领取,除非先将其重新托运。为了适应这种情况,我们在claim-check-out转换器上引入了remove-message布尔属性。此属性默认设置为false。但是,如果设置为true,则领取的消息将从MessageStore中删除,因此无法再次领取。

此功能会对存储空间产生影响,尤其是在基于内存的MapSimpleMessageStore的情况下,如果无法删除消息,最终会导致OutOfMemoryException。因此,如果您不希望进行多次领取,建议您将remove-message属性的值设置为true。以下示例展示了如何使用remove-message属性

<int:claim-check-out id="checkout"
        input-channel="checkoutChannel"
        message-store="testMessageStore"
        output-channel="output"
        remove-message="true"/>

关于消息存储的一句话

虽然我们很少关心领取检查的细节(只要它们有效),但您应该知道,Spring Integration 中实际领取检查(指针)的当前实现使用 UUID 来确保唯一性。

org.springframework.integration.store.MessageStore是一个用于存储和检索消息的策略接口。Spring Integration 提供了它的两个方便的实现

  • SimpleMessageStore:基于内存的Map实现(默认,适合测试)

  • JdbcMessageStore:使用 JDBC 通过关系数据库实现的实现