提交 0cea4572 编写于 作者: 茶陵後's avatar 茶陵後 👍

#21 spring integration 图片补充调整

上级 226e744a
# Spring Integration
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
# 错误处理
## 错误处理
正如本手册开头的[overview](./overview.html#overview)中所描述的, Spring 集成之类的面向消息的框架背后的主要动机之一是促进组件之间的松耦合。消息渠道起着重要的作用,因为生产者和消费者不必相互了解。然而,这些优点也有一些缺点。在松散耦合的环境中,有些事情会变得更加复杂,其中一个例子就是错误处理。
当将消息发送到通道时,最终处理该消息的组件可能在与发送方相同的线程中运行,也可能不在相同的线程中运行。如果使用一个简单的默认`DirectChannel`(当`<channel>`元素没有`<queue>`子元素且没有“task-executor”属性时),消息处理发生在发送初始消息的同一个线程中。在这种情况下,如果抛出了一个`Exception`,它可以被发送方捕获(或者如果它是一个未捕获的`RuntimeException`,它可能会传播通过发送方)。这与普通 爪哇 调用堆栈中的抛出异常操作具有相同的行为。
在调用者线程上运行的消息流可以通过消息网关(参见[消息传递网关](./gateway.html#gateway))或`MessagingTemplate`(参见[`MessagingTemplate`](./channel.html#channel-template))调用。在这两种情况下,默认的行为都是向调用方抛出任何异常。有关消息传递网关,请参见[错误处理](./gateway.html#gateway-error-handling),以了解如何引发异常以及如何配置网关将错误路由到错误通道的详细信息。当使用`MessagingTemplate`或直接发送到`MessageChannel`时,异常总是被抛给调用方。
当添加异步处理时,事情会变得相当复杂。例如,如果“channel”元素确实提供了一个“queue”子元素(在 Java&Annotations 配置中是`QueueChannel`),那么处理消息的组件在与发送方不同的线程中进行操作。当使用`ExecutorChannel`时也是如此。发送者可能已经将`Message`放入通道中,然后转移到其他东西上。通过使用标准的`Exception`抛出技术,无法将`Exception`直接抛回给发送方。相反,处理异步进程的错误要求错误处理机制也是异步的。
Spring 集成支持通过将错误发布到消息通道来对其组件进行错误处理。具体地说,`Exception`将成为 Spring 集成`ErrorMessage`的有效负载。然后将`Message`发送到消息通道,该消息通道的解析方式类似于“replychannel”解析。首先,如果在`Exception`发生时正在处理的请求`Message`包含一个“errorchannel”头(头名在`MessageHeaders.ERROR_CHANNEL`常量中定义),则`ErrorMessage`被发送到该通道。否则,错误处理程序将发送到一个“全局”通道,该通道的 Bean 名称是`errorChannel`(这也被定义为一个常数:`IntegrationContextUtils.ERROR_CHANNEL_BEAN_NAME`)。
默认的`errorChannel` Bean 是由框架在内部创建的。但是,如果你想要控制设置,则可以定义自己的设置。下面的示例展示了如何在 XML 配置中定义错误通道,该配置由容量`500`的队列支持:
Java
```
@Bean
QueueChannel errorChannel() {
return new QueueChannel(500);
}
```
XML
```
<int:channel id="errorChannel">
<int:queue capacity="500"/>
</int:channel>
```
| |默认的错误通道是`PublishSubscribeChannel`。|
|---|---------------------------------------------------------|
这里需要理解的最重要的一点是,基于消息传递的错误处理仅适用于在`TaskExecutor`中执行的 Spring 集成任务引发的异常。这不适用于在与发送方相同的线程中操作的处理程序引发的异常(例如,通过`DirectChannel`,如本节前面所述)。
| |当计划的 Poller 任务执行中出现异常时,这些异常被包装在`ErrorMessage`实例中,并发送到“errorchannel”。<br/>这是通过将`MessagePublishingErrorHandler`注入全局`taskScheduler` Bean 中来完成的。<br/>对于任何自定义`MessagePublishingErrorHandler`,都建议使用`MessagePublishingErrorHandler`。如果错误处理仍然必须使用标准的“errorchannel”集成流逻辑来完成。<br/>在这种情况下可以使用已注册的`integrationMessagePublishingErrorHandler` Bean。|
|---|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
要启用全局错误处理,请在该通道上注册一个处理程序。例如,你可以将 Spring Integration 的`ErrorMessageExceptionTypeRouter`配置为订阅到“errorchannel”的端点的处理程序。然后,该路由器可以基于`Exception`类型,在多个通道上传播错误消息。
从版本 4.3.10 开始, Spring 集成提供了`ErrorMessagePublisher``ErrorMessageStrategy`。你可以将它们用作发布`ErrorMessage`实例的通用机制。你可以在任何错误处理场景中调用或扩展它们。`ErrorMessageSendingRecoverer`将这个类扩展为`RecoveryCallback`实现,该实现可用于重试,例如[`RequestHandlerRetryAdvice`](./handler-advice.html#retry-advice)。`ErrorMessageStrategy`用于基于提供的异常和`AttributeAccessor`上下文构建`ErrorMessage`。它可以被注入任何`MessageProducerSupport``MessagingGatewaySupport``requestMessage`存储在`ErrorMessageUtils.INPUT_MESSAGE_CONTEXT_KEY`上下文中。`ErrorMessageStrategy`可以使用`requestMessage`作为它创建的`ErrorMessage`属性的`originalMessage``DefaultErrorMessageStrategy`就是这么做的。
从版本 5.2 开始,所有由框架组件抛出的`MessageHandlingException`实例中,包含一个组件`BeanDefinition`的资源和源,以确定一个配置点的异常形式。在 XML 配置的情况下,资源是一个 XML 文件路径,并源具有`id`属性的 XML 标记。对于 Java&Annotation 配置,资源是`@Configuration`类,而源是`@Bean`方法。在大多数情况下,目标集成流解决方案是基于开箱即用的组件及其配置选项的。当运行时发生异常时,堆栈跟踪中不涉及任何最终用户代码,因为执行是针对 bean 的,而不是针对它们的配置。 Bean 包括资源和源的定义有助于确定可能的配置错误并提供更好的开发人员体验。
从版本 5.4.3 开始,默认的错误通道配置为属性`requireSubscribers = true`,当此通道上没有订阅服务器时(例如,当应用程序上下文停止时),不会静默忽略消息。在这种情况下,将抛出一个`MessageDispatchingException`,它可能会在入站通道适配器的客户端回调中负地确认(或回滚)源系统中的原始消息,以用于重新交付或其他将来的考虑。要恢复以前的行为(忽略未分派的错误消息),全局集成属性`spring.integration.channels.error.requireSubscribers`必须设置为`false`。有关更多信息,请参见[全局属性](./configuration.html#global-properties)和[`PublishSubscribeChannel`配置](./channel.html#channel-configuration-pubsubchannel)(如果你手动配置全局`errorChannel`)。
\ No newline at end of file
# Spring 应用事件支持
## Spring `ApplicationEvent`支持
Spring 集成提供了对入站和出站`ApplicationEvents`的支持,如底层 Spring 框架所定义的那样。有关 Spring 对事件和侦听器的支持的更多信息,请参见[Spring Reference Manual](https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#context-functionality-events)
你需要在项目中包含此依赖项:
Maven
```
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-event</artifactId>
<version>5.5.9</version>
</dependency>
```
Gradle
```
compile "org.springframework.integration:spring-integration-event:5.5.9"
```
### 接收 Spring 应用事件
要接收事件并将其发送到通道,你可以定义 Spring Integration 的`ApplicationEventListeningMessageProducer`实例。这个类是 Spring 的`ApplicationListener`接口的实现。默认情况下,它将所有接收到的事件作为 Spring 集成消息传递。要根据事件的类型进行限制,可以使用“eventTypes”属性来配置要接收的事件类型列表。如果接收到的事件有一个`Message`实例作为其“源”,则该`Message`将按原样传递。否则,如果提供了基于 SPEL 的`payloadExpression`,则根据`ApplicationEvent`实例对其进行求值。如果事件的源不是`Message`实例,并且没有提供`payloadExpression`,则`ApplicationEvent`本身将作为有效负载传递。
从版本 4.2 开始,`ApplicationEventListeningMessageProducer`实现了`GenericApplicationListener`,并且可以被配置为不仅接受`ApplicationEvent`类型,还接受用于处理有效负载事件的任何类型(自 Spring Framework4.2 以来也支持这种类型)。当接受的事件是`PayloadApplicationEvent`的实例时,它的`payload`用于发送消息。
为了方便起见,提供了名称空间支持,以配置带有`inbound-channel-adapter`元素的`ApplicationEventListeningMessageProducer`,如下例所示:
```
<int-event:inbound-channel-adapter channel="eventChannel"
error-channel="eventErrorChannel"
event-types="example.FooEvent, example.BarEvent, java.util.Date"/>
<int:publish-subscribe-channel id="eventChannel"/>
```
在前面的示例中,与“event-types”(可选)属性指定的类型之一相匹配的所有应用程序上下文事件都作为 Spring 集成消息传递到名为“EventChannel”的消息通道。如果下游组件抛出异常,则将包含失败消息和异常的`MessagingException`发送到名为“EvenTerrorChannel”的通道。如果指定了 no`error-channel`,并且下游通道是同步的,则异常将传播给调用方。
使用 Java 配置相同的适配器:
```
@Bean
public ApplicationEventListeningMessageProducer eventsAdapter(
MessageChannel eventChannel, MessageChannel eventErrorChannel) {
ApplicationEventListeningMessageProducer producer =
new ApplicationEventListeningMessageProducer();
producer.setEventTypes(example.FooEvent.class, example.BarEvent.class, java.util.Date.class);
producer.setOutputChannel(eventChannel);
producer.setErrorChannel(eventErrorChannel);
return producer;
}
```
使用 Java DSL:
```
@Bean
public ApplicationEventListeningMessageProducer eventsAdapter() {
ApplicationEventListeningMessageProducer producer =
new ApplicationEventListeningMessageProducer();
producer.setEventTypes(example.FooEvent.class, example.BarEvent.class, java.util.Date.class);
return producer;
}
@Bean
public IntegrationFlow eventFlow(ApplicationEventListeningMessageProducer eventsAdapter,
MessageChannel eventErrorChannel) {
return IntegrationFlows.from(eventsAdapter, e -> e.errorChannel(eventErrorChannel))
.handle(...)
...
.get();
}
```
### 发送 Spring 应用程序事件
要发送 Spring `ApplicationEvents`,请创建`ApplicationEventPublishingMessageHandler`的一个实例,并将其注册到一个端点中。`MessageHandler`接口的此实现还实现了 Spring 的`ApplicationEventPublisherAware`接口,因此充当 Spring 集成消息和`ApplicationEvents`之间的桥梁。
为了方便起见,提供了名称空间支持,以配置带有`outbound-channel-adapter`元素的`ApplicationEventPublishingMessageHandler`元素,如下例所示:
```
<int:channel id="eventChannel"/>
<int-event:outbound-channel-adapter channel="eventChannel"/>
```
如果使用`PollableChannel`(例如`QueueChannel`),还可以提供`poller`元素的子元素。你还可以为该 Poller 提供`task-executor`引用。下面的示例演示了这两个方面:
```
<int:channel id="eventChannel">
<int:queue/>
</int:channel>
<int-event:outbound-channel-adapter channel="eventChannel">
<int:poller max-messages-per-poll="1" task-executor="executor" fixed-rate="100"/>
</int-event:outbound-channel-adapter>
<task:executor id="executor" pool-size="5"/>
```
在前面的示例中,发送到“EventChannel”通道的所有消息都作为`ApplicationEvent`实例发布到在相同的 Spring `ApplicationListener`中注册的任何相关`ApplicationContext`实例。如果消息的有效负载是`ApplicationEvent`,则按原样传递。否则,消息本身被包装在`MessagingEvent`实例中。
从版本 4.2 开始,你可以配置带有`publish-payload`布尔属性的`ApplicationEventPublishingMessageHandler``<int-event:outbound-channel-adapter>`),以按原样发布到应用程序上下文`payload`,而不是将其包装到`MessagingEvent`实例。
要使用 Java 配置来配置适配器:
```
@Bean
@ServiceActivator(inputChannel = "eventChannel")
public ApplicationEventPublishingMessageHandler eventHandler() {
ApplicationEventPublishingMessageHandler handler =
new ApplicationEventPublishingMessageHandler();
handler.setPublishPayload(true);
return handler;
}
```
使用 Java DSL:
```
@Bean
public ApplicationEventPublishingMessageHandler eventHandler() {
ApplicationEventPublishingMessageHandler handler =
new ApplicationEventPublishingMessageHandler();
handler.setPublishPayload(true);
return handler;
}
@Bean
// MessageChannel is "eventsFlow.input"
public IntegrationFlow eventsOutFlow(ApplicationEventPublishingMessageHandler eventHandler) {
return f -> f.handle(eventHandler);
}
```
\ No newline at end of file
# 馈源适配器
## 提要适配器
Spring 集成通过提要适配器为聚合提供支持。该实现基于[罗马框架](https://rometools.github.io/rome/)
你需要在项目中包含此依赖项:
Maven
```
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-feed</artifactId>
<version>5.5.9</version>
</dependency>
```
Gradle
```
compile "org.springframework.integration:spring-integration-feed:5.5.9"
```
Web 辛迪加是一种发布材料的方式,例如新闻报道,新闻稿,博客文章和其他项目,通常可以在网站上获得,但也可以在提要格式(例如 RSS 或 Atom)中获得。
Spring 集成通过其“提要”适配器为 Web 聚合提供了支持,并为其提供了方便的基于名称空间的配置。要配置“Feed”名称空间,在 XML 配置文件的头中包含以下元素:
```
xmlns:int-feed="http://www.springframework.org/schema/integration/feed"
xsi:schemaLocation="http://www.springframework.org/schema/integration/feed
https://www.springframework.org/schema/integration/feed/spring-integration-feed.xsd"
```
### feed 入站通道适配器
你真正需要为检索提要提供支持的唯一适配器是入站通道适配器。它允许你订阅特定的 URL。下面的示例展示了一种可能的配置:
```
<int-feed:inbound-channel-adapter id="feedAdapter"
channel="feedChannel"
url="https://feeds.bbci.co.uk/news/rss.xml">
<int:poller fixed-rate="10000" max-messages-per-poll="100" />
</int-feed:inbound-channel-adapter>
```
在前面的配置中,我们订阅了由`url`属性标识的 URL。
在检索新闻项目时,将其转换为消息,并将其发送到由`channel`属性标识的通道。每个消息的有效负载是`com.sun.syndication.feed.synd.SyndEntry`实例。每一个都封装了关于新闻项目的各种数据(内容、日期、作者和其他细节)。
入站提要通道适配器是一个轮询消费者。这意味着你必须提供一个 Poller 配置。然而,关于提要,你必须了解的一件重要事情是,它的内部工作方式与大多数其他轮询消费者略有不同。启动入站提要适配器时,它执行第一次轮询,并接收`com.sun.syndication.feed.synd.SyndEntryFeed`实例。该对象包含多个`SyndEntry`对象。每个条目存储在本地条目队列中,并基于`max-messages-per-poll`属性中的值释放,这样每个消息都包含一个条目。如果在从条目队列检索条目的过程中,队列已为空,则适配器尝试更新提要,从而在队列中填充更多条目(`SyndEntry`实例)(如果有可用的话)。否则,下一次对提要进行轮询的尝试将由 Poller 的触发器决定(在前面的配置中,每十秒钟进行一次轮询)。
### 重复条目
对提要进行轮询可能会导致条目已经被处理(“我已经阅读了该新闻项目,为什么要再次向我显示它?”) Spring 集成提供了一种方便的机制,以消除对重复条目的担心。每个提要条目都有一个“发布日期”字段。每次生成和发送新的`Message`时, Spring 集成都会在`MetadataStore`策略的实例中存储最新发布日期的值(参见[元数据存储](./meta-data-store.html#metadata-store))。
| |用于持久化最新发布日期的键是提要入站通道适配器组件的(必需的)`id`属性的值加上适配器配置中的`feedUrl`(如果有的话)。|
|---|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
### 其他选项
从版本 5.0 开始,已废弃的`com.rometools.fetcher.FeedFetcher`选项已被删除,并提供了用于`org.springframework.core.io.Resource`的重载`FeedEntryMessageSource`构造函数。当提要源不是 HTTP 端点,而是任何其他资源(例如 FTP 上的本地或远程)时,这很有用。在`FeedEntryMessageSource`逻辑中,这样的资源(或提供`URL`)由`SyndFeedInput`解析到用于前面提到的处理的`SyndFeed`对象。还可以将自定义的`SyndFeedInput`(例如,使用`allowDoctypes`选项)实例注入`FeedEntryMessageSource`
| |如果到提要的连接需要一些定制,例如连接和读取超时,则必须使用带有其`customizeConnection(HttpURLConnection)`覆盖功能的`org.springframework.core.io.UrlResource`扩展,而不是普通的`URL`注入到<br/>例如:<br/><br/>```<br/>@Bean<br/>@InboundChannelAdapter("feedChannel")<br/>FeedEntryMessageSource feedEntrySource() {<br/> UrlResource urlResource =<br/> new UrlResource(url) {<br/><br/> @Override<br/> protected void customizeConnection(HttpURLConnection connection) throws IOException {<br/> super.customizeConnection(connection);<br/> connection.setConnectTimeout(10000);<br/> connection.setReadTimeout(5000);<br/> }<br/> };<br/> return new FeedEntryMessageSource(urlResource, "myKey");<br/>}<br/>```|
|---|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
### Java DSL 配置
下面的 Spring 引导应用程序展示了如何使用 Java DSL 配置入站适配器的示例:
```
@SpringBootApplication
public class FeedJavaApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(FeedJavaApplication.class)
.web(false)
.run(args);
}
@Value("org/springframework/integration/feed/sample.rss")
private Resource feedResource;
@Bean
public MetadataStore metadataStore() {
PropertiesPersistingMetadataStore metadataStore = new PropertiesPersistingMetadataStore();
metadataStore.setBaseDirectory(tempFolder.getRoot().getAbsolutePath());
return metadataStore;
}
@Bean
public IntegrationFlow feedFlow() {
return IntegrationFlows
.from(Feed.inboundAdapter(this.feedResource, "feedTest")
.metadataStore(metadataStore()),
e -> e.poller(p -> p.fixedDelay(100)))
.channel(c -> c.queue("entries"))
.get();
}
}
```
\ No newline at end of file
此差异已折叠。
此差异已折叠。
# Pivotal Gemfire 和 Apache Geode 支持
## Pivotal Gemfire 和 Apache Geode 支持
Spring 集成为 Pivotal Gemfire 和 Apache Geode 提供了支持。
你需要在项目中包含此依赖项:
Maven
```
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-gemfire</artifactId>
<version>5.5.9</version>
</dependency>
```
Gradle
```
compile "org.springframework.integration:spring-integration-gemfire:5.5.9"
```
Gemfire 是一个分布式数据管理平台,它提供了一个键值数据网格以及先进的分布式系统功能,例如事件处理,连续查询和远程功能执行。本指南假定你熟悉商业[Pivotal Gemfire](https://pivotal.io/pivotal-gemfire)或开源[Apache Geode](https://geode.apache.org)
Spring 集成通过实现用于条目和连续查询事件的入站适配器、用于将条目写到缓存的出站适配器、以及消息和元数据存储和`GemfireLockRegistry`实现来提供对 Gemfire 的支持。 Spring 集成利用了[Spring Data for Pivotal GemFire](https://projects.spring.io/spring-data-gemfire)项目,在其组件上提供了一个薄的包装器。
从版本 5.1 开始, Spring Integration Gemfire 模块默认使用[Spring Data for Apache Geode](https://github.com/spring-projects/spring-data-geode)传递依赖关系。要为 Pivotal Gemfire 切换到基于 Pivotal Gemfire Spring 的商业数据,从依赖项中排除`spring-data-geode`,并添加`spring-data-gemfire`,如下 Maven 片段所示:
```
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-gemfire</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-geode</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-gemfire</artifactId>
</dependency>
```
要配置“INT-GFE”名称空间,在 XML 配置文件的头中包含以下元素:
```
xmlns:int-gfe="http://www.springframework.org/schema/integration/gemfire"
xsi:schemaLocation="http://www.springframework.org/schema/integration/gemfire
https://www.springframework.org/schema/integration/gemfire/spring-integration-gemfire.xsd"
```
### 入站通道适配器
当 Gemfire`EntryEvent`触发时,入站通道适配器在通道上生成消息。每当相关区域中的条目`CREATED``UPDATED``DESTROYED``INVALIDATED`时,Gemfire 都会生成事件。入站通道适配器允许你筛选这些事件的一个子集。例如,你可能希望仅在响应正在创建的条目时生成消息。此外,如果希望消息有效负载包含事件属性(如新的 entry 值),则入站通道适配器可以计算 SPEL 表达式。下面的示例展示了如何使用 SPEL 语言(在`expression`属性中)配置入站通道适配器:
```
<gfe:cache/>
<gfe:replicated-region id="region"/>
<int-gfe:inbound-channel-adapter id="inputChannel" region="region"
cache-events="CREATED" expression="newValue"/>
```
前面的配置使用 Spring Gemfire 的“GFE”命名空间创建了一个 Gemfire`Cache``Region``inbound-channel-adapter`元素需要对适配器监听事件的 Gemfire 区域进行引用。可选属性包括`cache-events`,它可以包含一个逗号分隔的事件类型列表,这些事件类型的消息是在输入通道上产生的。默认情况下,`CREATED``UPDATED`是启用的。如果不提供`channel`属性,则从`id`属性创建通道。这个适配器还支持`error-channel`。Gemfire[`EntryEvent`](https://geode.apache.org/releases/latest/javadoc/org/apache/geode/cache/entryevent.html)是`#root`评估的对象。下面的示例展示了一个替换键值的表达式:
```
expression="new something.MyEvent(key, oldValue, newValue)"
```
如果不提供`expression`属性,则消息有效负载就是 Gemfire`EntryEvent`本身。
| |此适配器符合 Spring 集成约定。|
|---|--------------------------------------------------------|
### 连续查询入站通道适配器
当 Gemfire 连续查询或`CqEvent`事件触发时,连续查询入站通道适配器在通道上生成消息。在版本`1.1`中, Spring Data 引入了连续查询支持,包括`ContinuousQueryListenerContainer`,这在 Gemfire 原生 API 上提供了一个很好的抽象。这个适配器需要对`ContinuousQueryListenerContainer`实例的引用,为给定的`query`创建一个侦听器,并执行查询。连续查询充当事件源,每当其结果集更改状态时,它都会触发事件源。
| |Gemfire 查询是用 OQL 编写的,其作用域是整个缓存(而不仅仅是一个区域)。<br/>此外,连续查询需要一个远程(即在单独的进程或远程主机中运行)缓存服务器。<br/>有关实现连续查询的更多信息,请参见[Gemfire 文档](https://gemfire82.docs.pivotal.io/docs-gemfire/gemfire_nativeclient/continuous-querying/continuous-querying.html)。|
|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
下面的配置创建了一个 Gemfire 客户端缓存(该实现需要一个远程缓存服务器,其地址被配置为池的子元素)、一个客户端区域和一个使用 Spring 数据的`ContinuousQueryListenerContainer`:
```
<gfe:client-cache id="client-cache" pool-name="client-pool"/>
<gfe:pool id="client-pool" subscription-enabled="true" >
<!--configure server or locator here required to address the cache server -->
</gfe:pool>
<gfe:client-region id="test" cache-ref="client-cache" pool-name="client-pool"/>
<gfe:cq-listener-container id="queryListenerContainer" cache="client-cache"
pool-name="client-pool"/>
<int-gfe:cq-inbound-channel-adapter id="inputChannel"
cq-listener-container="queryListenerContainer"
query="select * from /test"/>
```
连续查询入站通道适配器需要`cq-listener-container`属性,该属性必须包含对`ContinuousQueryListenerContainer`的引用。可选地,它接受`expression`属性,该属性使用 SPEL 转换`CqEvent`或根据需要提取单个属性。`cq-inbound-channel-adapter`提供了一个`query-events`属性,该属性包含一个以逗号分隔的事件类型列表,该事件类型的消息是在输入通道上产生的。可用的事件类型是`CREATED``UPDATED``DESTROYED``REGION_DESTROYED``REGION_INVALIDATED`。默认情况下,`CREATED``UPDATED`是启用的。其他可选属性包括`query-name`(它提供了一个可选的查询名称)、`expression`(它的工作原理如上一节所述)和`durable`(一个布尔值,指示查询是否持久——默认情况下它是 false)。如果不提供`channel`,则通道将从`id`属性创建。这个适配器还支持`error-channel`
| |此适配器符合 Spring 集成约定。|
|---|--------------------------------------------------------|
### 出站通道适配器
出站通道适配器写入从消息有效负载映射的缓存项。在其最简单的形式中,它期望类型`java.util.Map`的有效负载,并将映射条目放入其配置的区域中。下面的示例展示了如何配置出站通道适配器:
```
<int-gfe:outbound-channel-adapter id="cacheChannel" region="region"/>
```
给定上述配置,如果有效负载不是`Map`,则会引发异常。此外,你可以配置出站通道适配器,以通过使用 SPEL 创建高速缓存条目的映射。下面的示例展示了如何做到这一点:
```
<int-gfe:outbound-channel-adapter id="cacheChannel" region="region">
<int-gfe:cache-entries>
<entry key="payload.toUpperCase()" value="payload.toLowerCase()"/>
<entry key="'thing1'" value="'thing2'"/>
</int-gfe:cache-entries>
</int-gfe:outbound-channel-adapter>
```
在前面的配置中,内部元素(`cache-entries`)在语义上等同于 Spring’map’元素。适配器将`key``value`属性解释为 SPEL 表达式,并将消息作为求值上下文。请注意,这可以包含任意的缓存条目(不仅仅是从消息派生的条目),并且文字值必须用单引号括起来。在前面的示例中,如果发送到`cacheChannel`的消息具有`String``Hello`的有效负载,则在缓存区域中写入两个条目(`[HELLO:hello, thing1:thing2]`)(要么创建要么更新)。此适配器还支持`order`属性,如果将其绑定到`PublishSubscribeChannel`,则该属性可能很有用。
### Gemfire 消息存储
正如 EIP 中所描述的,[消息存储](https://www.enterpriseintegrationpatterns.com/MessageStore.html)允许你持久化消息。在处理具有缓冲消息能力的组件(`QueueChannel``Aggregator``Resequencer`,以及其他)时,如果可靠性是一个问题,这可能是有用的。在 Spring 集成中,`MessageStore`策略接口还为[索赔检查](https://www.enterpriseintegrationpatterns.com/StoreInLibrary.html)模式提供了基础,这也在 EIP 中进行了描述。
Spring Integration 的 Gemfire 模块提供了`GemfireMessageStore`,这是`MessageStore`策略(主要由`QueueChannel``ClaimCheck`模式使用)和`MessageGroupStore`策略(主要由`Aggregator``Resequencer`模式使用)的一种实现。
下面的示例通过使用`spring-gemfire`命名空间(不要与`spring-integration-gemfire`命名空间混淆)来配置缓存和区域:
```
<bean id="gemfireMessageStore" class="o.s.i.gemfire.store.GemfireMessageStore">
<constructor-arg ref="myRegion"/>
</bean>
<gfe:cache/>
<gfe:replicated-region id="myRegion"/>
<int:channel id="somePersistentQueueChannel">
<int:queue message-store="gemfireMessageStore"/>
<int:channel>
<int:aggregator input-channel="inputChannel" output-channel="outputChannel"
message-store="gemfireMessageStore"/>
```
通常,希望在客户机-服务器配置中在一个或多个远程缓存服务器中维护消息存储。在这种情况下,你应该配置一个客户机缓存、一个客户机区域和一个客户机池,并将该区域注入`MessageStore`。下面的示例展示了如何做到这一点:
```
<bean id="gemfireMessageStore"
class="org.springframework.integration.gemfire.store.GemfireMessageStore">
<constructor-arg ref="myRegion"/>
</bean>
<gfe:client-cache/>
<gfe:client-region id="myRegion" shortcut="PROXY" pool-name="messageStorePool"/>
<gfe:pool id="messageStorePool">
<gfe:server host="localhost" port="40404" />
</gfe:pool>
```
请注意,`pool`元素被配置为缓存服务器的地址(你可以在此替换定位器)。该区域被配置为“代理”,因此不会在本地存储任何数据。该区域的`id`对应于缓存服务器中同名的区域。
从版本 4.3.12 开始,`GemfireMessageStore`支持键`prefix`选项,以允许在同一 Gemfire 区域上的存储实例之间进行区分。
### Gemfire Lock 注册表
从版本 4.0 开始,`GemfireLockRegistry`是可用的。某些组件(例如,聚合器和重排序程序)使用从`LockRegistry`实例获得的锁,以确保在任何给定的时间只有一个线程正在操作组。`DefaultLockRegistry`在单个组件中执行此功能。现在,你可以在这些组件上配置一个外部锁注册中心。当你使用与`GemfireLockRegistry`共享的`MessageGroupStore`时,它可以跨多个应用程序实例提供此功能,从而一次只有一个实例可以操作组。
| |其中一个`GemfireLockRegistry`构造函数需要一个`Region`作为参数。<br/>它用于从`getDistributedLock()`方法获得一个`Lock`<br/>该操作需要`GLOBAL`用于`Region`的作用域。,<br/>另一个构造函数需要一个`Cache`,而`Region`是用`GLOBAL`作用域和名称`LockRegistry`创建的。|
|---|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
### Gemfire 元数据存储
4.0 版本引入了一个新的基于 Gemfire 的`MetadataStore`[元数据存储](./meta-data-store.html#metadata-store))实现。你可以使用`GemfireMetadataStore`在应用程序重新启动期间维护元数据状态。这个新的`MetadataStore`实现可以与适配器一起使用,例如:
* [馈入入通道适配器](./feed.html#feed-inbound-channel-adapter)
* [读取文件](./file.html#file-reading)
* [FTP 入站通道适配器](./ftp.html#ftp-inbound)
* [SFTP 入站通道适配器](./sftp.html#sftp-inbound)
要让这些适配器使用新的`GemfireMetadataStore`,请声明一个 Spring Bean,其 Bean 名称为`metadataStore`。提要入站通道适配器自动拾取并使用声明的`GemfireMetadataStore`
| |`GemfireMetadataStore`还实现了`ConcurrentMetadataStore`,从而可以在多个应用程序实例之间可靠地共享它,只有一个实例可以存储或修改键值。<br/>这些方法根据该区域的范围和数据策略提供不同级别的并发保证。<br/>它们在对等缓存和客户机-服务器缓存中实现,但在对等区域中不允许。具有`NORMAL``EMPTY`数据策略的。|
|---|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| |从版本 5.0 开始,`GemfireMetadataStore`还实现了`ListenableMetadataStore`,它允许你通过向存储提供`MetadataStoreListener`实例来侦听缓存事件,如下例所示:|
|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
```
GemfireMetadataStore metadataStore = new GemfireMetadataStore(cache);
metadataStore.addListener(new MetadataStoreListenerAdapter() {
@Override
public void onAdd(String key, String value) {
...
}
});
```
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
# JMX 支持
### JMX 支持
Spring 集成提供了用于接收和发布 JMX 通知的通道适配器。
你需要在项目中包含此依赖项:
Maven
```
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-jmx</artifactId>
<version>5.5.9</version>
</dependency>
```
Gradle
```
compile "org.springframework.integration:spring-integration-jmx:5.5.9"
```
入站通道适配器允许轮询 JMX MBean 属性值,出站通道适配器允许调用 JMX MBean 操作。
#### 通知-监听通道适配器
通知监听通道适配器需要一个 JMX,用于发布此侦听器应注册到的通知的 MBean。一个非常简单的配置可能类似于以下内容:
```
<int-jmx:notification-listening-channel-adapter id="adapter"
channel="channel"
object-name="example.domain:name=publisher"/>
```
| |在启动时,`notification-listening-channel-adapter`使用`MBeanServer`注册,默认的 Bean 名称是`mbeanServer`,这恰好是使用 Spring 的`<context:mbean-server/>`元素时生成的相同的 Bean 名称。<br/>如果需要使用不同的名称,请确保包含`mbean-server`属性。|
|---|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
适配器还可以接受对`NotificationFilter`和“handback”对象的引用,以提供与每个通知一起回传的某些上下文。这两个属性都是可选的。将前面的示例扩展到包括这些属性以及显式的`MBeanServer` Bean 名称,将产生以下示例:
```
<int-jmx:notification-listening-channel-adapter id="adapter"
channel="channel"
mbean-server="someServer"
object-name="example.domain:name=somePublisher"
notification-filter="notificationFilter"
handback="myHandback"/>
```
通知侦听通道适配器是事件驱动的,并直接向`MBeanServer`注册。它不需要任何 Poller 配置。
| |仅对于这个组件,`object-name`属性可以包含一个对象名模式(例如,<br/>“org.something:type=mytype,name=\*”)。,在这种情况下,适配器接收来自所有具有匹配该模式的对象名的 MBean 的通知。,此外,<br/>`object-name`属性可以包含对`<util:list>`对象名称模式的 SPEL 引用,如下例所示:<br/><br/>```<br/><jmx:notification-listening-channel-adapter id="manyNotificationsAdapter"<br/> channel="manyNotificationsChannel"<br/> object-name="#{patterns}"/><br/><br/><util:list id="patterns"><br/> <value>org.foo:type=Foo,name=*</value><br/> <value>org.foo:type=Bar,name=*</value><br/></util:list><br/>```<br/>启用调试级别日志时,将记录定位的 MBean 的名称。|
|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
#### 通知-发布通道适配器
通知发布通道适配器相对简单。它在配置中只需要一个 JMX 对象名,如下例所示:
```
<context:mbean-export/>
<int-jmx:notification-publishing-channel-adapter id="adapter"
channel="channel"
object-name="example.domain:name=publisher"/>
```
它还要求在上下文中存在`MBeanExporter`。这就是为什么`<context:mbean-export/>`元素也显示在前面的示例中的原因。
当消息被发送到此适配器的通道时,将根据消息内容创建通知。如果有效负载是`String`,则作为通知的`message`文本传递。任何其他有效负载类型都将作为通知的`userData`传递。
JMX 通知还具有`type`,并且应该是以点分隔的`String`。有两种方法可以提供`type`。始终优先考虑与`JmxHeaders.NOTIFICATION_TYPE`键关联的消息标头值。或者,你可以在配置中提供一个 fallback`default-notification-type`属性,如下例所示:
```
<context:mbean-export/>
<int-jmx:notification-publishing-channel-adapter id="adapter"
channel="channel"
object-name="example.domain:name=publisher"
default-notification-type="some.default.type"/>
```
#### 属性-轮询通道适配器
当你需要定期检查通过 MBean 作为托管属性提供的某些值时,属性轮询通道适配器非常有用。可以以与 Spring 集成中的任何其他轮询适配器相同的方式配置 Poller(或者可以依赖默认的 Poller)。需要`object-name``attribute-name`。还需要一个 mBeanServer 引用。但是,默认情况下,它会自动检查名为`mbeanServer`的 Bean,与通知侦听通道适配器[前面描述的](#jmx-notification-listening-channel-adapter)相同。下面的示例展示了如何使用 XML 配置属性轮询通道适配器:
```
<int-jmx:attribute-polling-channel-adapter id="adapter"
channel="channel"
object-name="example.domain:name=someService"
attribute-name="InvocationCount">
<int:poller max-messages-per-poll="1" fixed-rate="5000"/>
</int-jmx:attribute-polling-channel-adapter>
```
#### 树轮询通道适配器
树轮询通道适配器查询 JMX MBean 树,并发送一条带有有效负载的消息,该负载是与查询匹配的对象的图形。默认情况下,MBean 映射到原语和简单对象,例如`Map``List`和数组。这样做允许简单地转换到(例如)JSON。还需要一个 mBeanServer 引用。但是,默认情况下,它会自动检查名为`mbeanServer`的 Bean,与通知监听通道适配器[前面描述的](#jmx-notification-listening-channel-adapter)相同。下面的示例展示了如何使用 XML 配置树轮询通道适配器:
```
<int-jmx:tree-polling-channel-adapter id="adapter"
channel="channel"
query-name="example.domain:type=*">
<int:poller max-messages-per-poll="1" fixed-rate="5000"/>
</int-jmx:tree-polling-channel-adapter>
```
前面的示例包括所选 MBean 上的所有属性。你可以通过提供一个配置了适当过滤器的`MBeanObjectConverter`来过滤属性。可以通过使用`converter`属性提供转换器作为 Bean 定义的引用,或者可以使用内部`<bean/>`定义。 Spring 集成提供了一个`DefaultMBeanObjectConverter`,它可以在其构造函数参数中接受一个`MBeanAttributeFilter`
Spring 集成提供了两个标准过滤器。`NamedFieldsMBeanAttributeFilter`允许你指定要包含的属性列表。`NotNamedFieldsMBeanAttributeFilter`允许你指定要排除的属性列表。你还可以实现自己的过滤器。
#### 操作调用通道适配器
操作调用通道适配器支持对 MBean 公开的任何托管操作的消息驱动调用。每个调用都需要调用操作名和目标 MBean 的对象名。这两个都必须由适配器配置显式提供,或者分别通过`JmxHeaders.OBJECT_NAME``JmxHeaders.OPERATION_NAME`消息头提供:
```
<int-jmx:operation-invoking-channel-adapter id="adapter"
object-name="example.domain:name=TestBean"
operation-name="ping"/>
```
然后适配器只需要能够发现`mbeanServer` Bean。如果需要一个不同的 Bean 名称,则为`mbean-server`属性提供一个引用。
消息的有效负载被映射到操作的参数(如果有的话)。带有`String`键的`Map`类型负载被视为名称/值对,而`List`或数组被作为简单的参数列表(没有显式的参数名称)传递。如果操作需要一个参数值,那么有效负载可以表示这个参数值。此外,如果操作不需要参数,则有效负载将被忽略。
如果你希望公开一个通道,以便由不需要包含头的消息调用单个公共操作,那么最后一个选项效果很好。
#### 操作调用出站网关
Spring 与操作调用通道适配器类似,集成还提供了一个操作调用出站网关,当需要返回值时,可以在处理非 void 操作时使用该网关。返回值作为消息有效负载发送到网关指定的`reply-channel`。下面的示例展示了如何使用 XML 配置操作调用出站网关:
```
<int-jmx:operation-invoking-outbound-gateway request-channel="requestChannel"
reply-channel="replyChannel"
object-name="o.s.i.jmx.config:type=TestBean,name=testBeanGateway"
operation-name="testWithReturn"/>
```
如果不提供`reply-channel`属性,则将回复消息发送到由`IntegrationMessageHeaderAccessor.REPLY_CHANNEL`标头标识的通道。该消息头通常由消息流的入口点自动创建,例如任何网关组件。但是,如果消息流是通过手动创建 Spring 集成消息并将其直接发送到通道来启动的,则必须显式地指定消息头,或者使用`reply-channel`属性。
#### MBean 出口商
Spring 当`IntegrationMBeanExporter`被配置时,集成组件本身可以作为 MBean 公开。要创建`IntegrationMBeanExporter`的实例,定义 Bean 并提供对`MBeanServer`的引用和域名(如果需要)。可以省略这个域,在这种情况下,默认域是`org.springframework.integration`。下面的示例展示了如何声明`IntegrationMBeanExporter`实例和关联的`MBeanServer`实例:
```
<int-jmx:mbean-export id="integrationMBeanExporter"
default-domain="my.company.domain" server="mbeanServer"/>
<bean id="mbeanServer" class="org.springframework.jmx.support.MBeanServerFactoryBean">
<property name="locateExistingServerIfPossible" value="true"/>
</bean>
```
| |MBean 输出器与 Spring Core 中提供的输出器是正交的。<br/>它注册消息通道和消息处理程序,但不注册本身。<br/>通过使用标准`<context:mbean-export/>`标记,可以公开导出程序本身(以及 Spring 集成中的某些其他组件),<br/>导出程序附带了一些度量指标,例如,计算处理程序的数量和排队消息的数量。<br/><br/>它还具有一个有用的操作,如[有序停机管理运行](#jmx-mbean-shutdown)中所讨论的。|
|---|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
Spring Integration4.0 引入了`@EnableIntegrationMBeanExport`注释,以允许方便地配置类型`integrationMbeanExporter` Bean 的默认`IntegrationMBeanExporter``@Configuration`类级别的几个有用选项。下面的示例展示了如何配置这个 Bean:
```
@Configuration
@EnableIntegration
@EnableIntegrationMBeanExport(server = "mbeanServer", managedComponents = "input")
public class ContextConfiguration {
@Bean
public MBeanServerFactoryBean mbeanServer() {
return new MBeanServerFactoryBean();
}
}
```
如果需要提供更多选项或具有几个`IntegrationMBeanExporter`bean(例如用于不同的 MBean 服务器或避免与标准 Spring `MBeanExporter`冲突——例如通过`@EnableMBeanExport`),则可以将`IntegrationMBeanExporter`配置为通用 Bean。
##### MBean 对象名
应用程序中的所有`MessageChannel``MessageHandler``MessageSource`实例都由 MBean Exporter 包装,以提供管理和监视功能。下表列出了为每个组件类型生成的 JMX 对象名:
|Component Type|对象名称|
|--------------|----------------------------------------------------------------------------|
|MessageChannel|```<br/> `o.s.i:type=MessageChannel,name=<channelName>`<br/>```|
|MessageSource |```<br/> `o.s.i:type=MessageSource,name=<channelName>,bean=<source>`<br/>```|
|MessageHandler|```<br/> `o.s.i:type=MessageSource,name=<channelName>,bean=<source>`<br/>```|
源和处理程序的对象名中的`bean`属性接受下表中的一个值:
| Bean Value |说明|
|--------------|-----------------------------------------------------------------------------------------------------------------------------|
| endpoint |Bean 封闭端点的名称(例如`<service-activator>`),如果有一个|
| anonymous |Bean 表示封闭端点没有用户指定的名称,因此 JMX 名称是输入通道名称。|
| internal |对于众所周知的 Spring 集成缺省组件|
|handler/source|以上都不是。<br/>返回被监视对象的`toString()`方法(处理程序或源)|
可以通过在`object-name-static-properties`属性中提供对`Properties`对象的引用,将自定义元素追加到对象名。
此外,由于 Spring Integration3.0,你可以通过设置`ObjectNamingStrategy`属性来使用自定义[`ObjectNamingStrategy`](https://DOCS. Spring.io/ Spring/DOCS/current/javadoc-api/org/springframework/jmx/export/naming/objectnamingstrategy.html)。这样做可以对 MBean 的命名进行更大的控制,例如将所有集成 MBean 分组为“集成”类型。下面的示例展示了一种可能的自定义命名策略实现:
```
public class Namer implements ObjectNamingStrategy {
private final ObjectNamingStrategy realNamer = new KeyNamingStrategy();
@Override
public ObjectName getObjectName(Object managedBean, String beanKey) throws MalformedObjectNameException {
String actualBeanKey = beanKey.replace("type=", "type=Integration,componentType=");
return realNamer.getObjectName(managedBean, actualBeanKey);
}
}
```
`beanKey`参数是一个`String`,它包含标准的对象名,从`default-domain`开始,并包括任何其他的静态属性。前面的示例将标准`type`部分移动到`componentType`,并将`type`设置为“集成”,从而能够在一个查询中选择所有集成 MBean:`my.domain:type=Integration,\*`。这样做还可以在 VisualVM 等工具中将 bean 分组到域下的一个树条目下。
| |默认的命名策略是[`MetadataNamingStrategy`](https://DOCS. Spring.io/ Spring/DOCS/current/javadoc-api/org/springframework/jmx/export/naming/metadatanamingstrategy.html)。<br/>导出人员将`default-domain`传播到该对象,以便在解析 Bean 键失败时让它生成一个后备对象名,<br/>如果你的自定义命名策略是`MetadataNamingStrategy`(或它的一个子类),导出程序不传播`default-domain`<br/>你必须在策略 Bean 上对其进行配置。|
|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
从版本 5.1 开始;任何 Bean 名称(由对象名称中的`name`键表示),如果它们包含 Java 标识符(或句号`.`)中不允许的任何字符,都将被引用。
##### JMX 改进
版本 4.2 引入了一些重要的改进,代表了对框架中的 JMX 支持的一次相当大的改革。这些结果导致了 JMX 统计数据收集的性能的显著改善,并对其进行了更多的控制。然而,在一些特定的(不常见的)情况下,它对用户代码有一些影响。下文详细介绍了这些变化,必要时请谨慎从事。
@IntegrationManagedResource
`@ManagedResource`注释类似,`@IntegrationManagedResource`将一个类标记为有资格作为 MBean 导出。但是,只有当应用程序上下文具有`IntegrationMBeanExporter`时,才会导出它。
Spring 某些集成类(在`org.springframework.integration`)包中)以前用`@ManagedResource`注释,现在用`@ManagedResource``@IntegrationManagedResource`注释。这是为了向后兼容(参见下一项)。这样的 MBean 通过任何上下文`MBeanServer``IntegrationMBeanExporter`导出(但不是两者都导出——如果两个出口商都存在,则如果 Bean 匹配`managed-components`模式,则 Bean 由集成出口商导出)。
MBean Exporter Bean 名称模式
以前,`managed-components`模式仅包含。如果 Bean 名称与其中一种模式相匹配,则该名称将被包括在内。现在,可以通过在模式前加上`!`来否定该模式。例如,`!thing*, things`匹配所有不以`thing`开头的 Bean 名称,但`things`除外。模式是从左到右计算的。第一场比赛(正面或负面)获胜,然后不再应用其他模式。
| |将此语法添加到模式中会导致一个可能的(尽管可能不太可能)问题,<br/>如果你的 Bean 名为`"!thing"`,并且你在 MBean Exporter 的`managed-components`模式中包含了`!thing`的模式,它不再匹配;模式现在匹配所有未命名`thing`的 bean。<br/>在这种情况下,你可以使用`\`在模式中转义`!`。<br/>`\!thing`模式匹配名为`!thing`的 Bean 的 Bean 模式。|
|---|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
整合-------------------------------------------------------
`IntegrationMBeanExporter`不再实现`SmartLifecycle`。这意味着`start()`和`stop()`操作不再可用于注册和取消注册 MBean。MBean 现在在上下文初始化期间注册,在上下文被销毁时取消注册。
##### 有序关停托管运行
MBean Exporter 允许一个 JMX 操作以有序的方式关闭应用程序。它是在停止 JVM 之前使用的。下面的示例展示了如何使用它:
```
public void stopActiveComponents(long howLong)
```
其用途和操作在[有序关机](./shutdown.html#jmx-shutdown)中进行了说明。
\ No newline at end of file
此差异已折叠。
此差异已折叠。
# Kotlin DSL
## Kotlin dsl
Kotlin DSL 是[Java DSL](./dsl.html#java-dsl)的包装器和扩展,其目的是使 Spring 上的集成开发尽可能平滑和简单,并与现有的 Java API 和 Kotlin 语言特定的结构具有互操作性。
所有你需要开始的只是`org.springframework.integration.dsl.integrationFlow`的导入-一个 Kotlin DSL 的重载全局函数。
对于作为 lambdas 的`IntegrationFlow`定义,我们通常不需要 Kotlin 中的任何其他内容,只需要像这样声明 Bean:
```
@Bean
fun oddFlow() =
IntegrationFlow { flow ->
flow.handle<Any> { _, _ -> "odd" }
}
```
在这种情况下, Kotlin 理解 Lambda 应该被转换为`IntegrationFlow`匿名实例,并且目标 Java DSL 处理器将此构造正确地解析为 Java 对象。
作为上述结构的替代方案以及为了与下面解释的用例保持一致,应该使用 Kotlin-specif DSL 来声明**建造者**模式样式中的集成流:
```
@Bean
fun flowLambda() =
integrationFlow {
filter<String> { it === "test" }
wireTap {
handle { println(it.payload) }
}
transform<String, String> { it.toUpperCase() }
}
```
这样的全局`integrationFlow()`函数需要对`KotlinIntegrationFlowDefinition``IntegrationFlowDefinition`的 Kotlin 包装器)使用构建器样式的 lambda,并生成一个常规的`IntegrationFlow`lambda 实现。请参阅下面的更多重载`integrationFlow()`变体。
许多其他场景需要从数据源启动`IntegrationFlow`(例如`JdbcPollingChannelAdapter``JmsInboundGateway`或仅从现有的`MessageChannel`)。为此目的, Spring 集成 Java DSL 提供了一个`IntegrationFlows`工厂及其大量的重载`from()`方法。这个工厂也可用于:
```
@Bean
fun flowFromSupplier() =
IntegrationFlows.from<String>({ "bar" }) { e -> e.poller { p -> p.fixedDelay(10).maxMessagesPerPoll(1) } }
.channel { c -> c.queue("fromSupplierQueue") }
.get()
```
但遗憾的是,并非所有`from()`方法都与 Kotlin 结构兼容。为了弥补差距,该项目提供了一个围绕`IntegrationFlows`工厂的 Kotlin DSL。它被实现为一组重载的`integrationFlow()`函数。用一个消费者为`KotlinIntegrationFlowDefinition`将流的其余部分声明为`IntegrationFlow`lambda,以重用上述经验,并最终避免`get()`调用。例如:
```
@Bean
fun functionFlow() =
integrationFlow<Function<String, String>>({ beanName("functionGateway") }) {
transform<String, String> { it.toUpperCase() }
}
@Bean
fun messageSourceFlow() =
integrationFlow(MessageProcessorMessageSource { "testSource" },
{ poller { it.fixedDelay(10).maxMessagesPerPoll(1) } }) {
channel { queue("fromSupplierQueue") }
}
```
此外, Kotlin 为 Java DSL API 提供了扩展,这需要对 Kotlin 结构进行一些改进。例如,`IntegrationFlowDefinition<*>`需要对具有`Class<P>`参数的许多方法进行具体化:
```
@Bean
fun convertFlow() =
integrationFlow("convertFlowInput") {
convert<TestPojo>()
}
```
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
# 前言
## 要求
本节详细介绍了兼容的[Java](https://www.oracle.com/technetwork/java/javase/downloads/index.html)[Spring Framework](https://spring.io/projects/spring-framework)版本。
### 兼容的 Java 版本
对于 Spring Integration5.5.x,最小的兼容 Java 版本是 Java SE8。不支持旧版本的 Java。
### Spring 框架的兼容版本
Spring 集成 5.5.x 需要 Spring 框架 5.3 或更高版本。
## 代码约定
Spring Framework2.0 引入了对名称空间的支持,这简化了应用程序上下文的 XML 配置,并让 Spring 集成提供广泛的名称空间支持。
在这个参考指南中,`int`名称空间前缀用于 Spring Integration 的核心名称空间支持。每个 Spring 集成适配器类型(也称为模块)提供其自己的名称空间,该名称空间通过使用以下约定进行配置:
下面的示例显示了使用中的`int``int-event``int-stream`名称空间:
```
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-webflux="http://www.springframework.org/schema/integration/webflux"
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/webflux
https://www.springframework.org/schema/integration/webflux/spring-integration-webflux.xsd
http://www.springframework.org/schema/integration/stream
https://www.springframework.org/schema/integration/stream/spring-integration-stream.xsd">
</beans>
```
有关 Spring 集成的名称空间支持的详细说明,请参见[命名空间支持](./configuration.html#configuration-namespace)
| |名称空间前缀可以自由选择。,<br/>你甚至可以选择完全不使用任何名称空间前缀,<br/>因此,你应该应用最适合你的应用程序的约定,<br/>不过,请注意,SpringSource Tool Suite 在 Spring 集成中使用了与本参考指南中使用的相同的名称空间约定。|
|---|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
## 本指南中的约定
在某些情况下,为了帮助在指定长的完全限定类名称时进行格式化,我们将`org.springframework`缩短为`o.s`,将`org.springframework.integration`缩短为`o.s.i`,例如使用`o.s.i.transaction.TransactionSynchronizationFactory`
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
# 额外资源
## 额外资源
关于 Spring 积分的明确的信息源是[Spring Integration Home](https://projects.spring.io/spring-integration/)at[https://spring.io](https://spring.io)。该网站是一个信息中心,是查找有关该项目的最新公告以及文章、博客和新示例应用程序链接的最佳场所。
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册