元数据存储

许多外部系统、服务或资源不支持事务(例如 Twitter、RSS、文件系统等),也无法将数据标记为已读。此外,有时您可能需要在某些集成解决方案中实现企业集成模式(Enterprise Integration Pattern)中的幂等接收者(idempotent receiver)。为了实现这一目标,并在与外部系统进行下一次交互或处理下一条消息之前存储端点的一些先前状态,Spring Integration 提供了元数据存储组件,作为 org.springframework.integration.metadata.MetadataStore 接口的一个实现,遵循通用的键值约定。

元数据存储旨在存储各种通用元数据(例如,已处理的最后一条 feed 条目的发布日期),以帮助 feed 适配器等组件处理重复项。如果一个组件没有直接提供 MetadataStore 的引用,查找元数据存储的算法如下:首先,在应用上下文中查找 ID 为 metadataStore 的 bean。如果找到,则使用它。否则,创建一个 SimpleMetadataStore 的新实例,这是一个内存实现,仅在当前运行的应用上下文生命周期内持久化元数据。这意味着在重启后,您可能会遇到重复条目。

如果您需要在应用上下文重启之间持久化元数据,框架提供了以下持久化 MetadataStores

PropertiesPersistingMetadataStore 由属性文件和一个 PropertiesPersister 提供支持。

默认情况下,它仅在应用上下文正常关闭时持久化状态。它实现了 Flushable 接口,因此您可以通过调用 flush() 来随时持久化状态。以下示例展示了如何使用 XML 配置 'PropertiesPersistingMetadataStore'

<bean id="metadataStore"
    class="org.springframework.integration.metadata.PropertiesPersistingMetadataStore"/>

或者,您可以提供自己的 MetadataStore 接口实现(例如 JdbcMetadataStore),并将其在应用上下文中配置为一个 bean。

从 4.0 版本开始,SimpleMetadataStorePropertiesPersistingMetadataStoreRedisMetadataStore 实现了 ConcurrentMetadataStore 接口。它们提供了原子更新功能,并且可以在多个组件或应用实例中共享使用。

幂等接收者与元数据存储

当需要过滤已处理过的入站消息并可以丢弃它或在丢弃时执行其他逻辑时,元数据存储对于实现企业集成模式(EIP)的幂等接收者(idempotent receiver)模式非常有用。以下配置显示了一个如何实现此目的的示例

<int:filter input-channel="serviceChannel"
			output-channel="idempotentServiceChannel"
			discard-channel="discardChannel"
			expression="@metadataStore.get(headers.businessKey) == null"/>

<int:publish-subscribe-channel id="idempotentServiceChannel"/>

<int:outbound-channel-adapter channel="idempotentServiceChannel"
                              expression="@metadataStore.put(headers.businessKey, '')"/>

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

幂等条目的 value 可以是一个过期日期,在此日期之后,该条目应由某个计划的清理器从元数据存储中移除。

MetadataStoreListener

某些元数据存储(目前只有 zookeeper)支持注册监听器以在项目变更时接收事件,示例如下

public interface MetadataStoreListener {

	void onAdd(String key, String value);

	void onRemove(String key, String oldValue);

	void onUpdate(String key, String newValue);
}

更多信息请参阅Javadoc。如果您只对部分事件感兴趣,可以继承 MetadataStoreListenerAdapter