# Stomp 支持
# stomp 支持
Spring 集成版本 4.2 引入了 STOMP(简单文本定向消息传递协议)客户端支持。它基于 Spring 框架的消息传递模块 STOMP 包中的体系结构、基础设施和 API。 Spring 集成使用 Spring Stomp 组件中的许多(例如StompSession
和StompClientSupport
)。有关更多信息,请参见 Spring 框架参考手册中的Spring Framework STOMP Support (opens new window)章节。
你需要在项目中包含此依赖项:
Maven
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-stomp</artifactId>
<version>5.5.9</version>
</dependency>
Gradle
compile "org.springframework.integration:spring-integration-stomp:5.5.9"
对于服务器端组件,你需要添加org.springframework:spring-websocket
和/或io.projectreactor.netty:reactor-netty
依赖关系。
# 概述
要配置 STOMP,你应该从 STOMP 客户机对象开始。 Spring 框架提供了以下实现方式:
WebSocketStompClient
:构建在 Spring WebSocket API 之上,支持标准的 JSR-356 WebSocket、 Jetty 9,以及用于基于 HTTP 的 WebSocket SockJS 仿真的 SockJS 和 SockJS 客户端。ReactorNettyTcpStompClient
:构建于ReactorNettyTcpClient
项目的reactor-netty
之上。
你可以提供任何其他StompClientSupport
实现。参见这些类的Javadoc (opens new window)。
将StompClientSupport
类设计为工厂,以生成针对所提供的StompSessionHandler
的StompSession
,并通过回调对StompSessionHandler
和StompSession
的抽象来完成所有剩余的工作。通过 Spring 集成适配器抽象,我们需要提供一些托管共享对象,以将我们的应用程序表示为具有唯一会话的 Stomp 客户机。为此, Spring 集成提供了StompSessionManager
的抽象,以管理在任意提供的单身StompSession
之间的StompSessionHandler
。这允许对特定的 Stomp 代理使用入站或出站通道适配器(或两者)。有关更多信息,请参见StompSessionManager
(及其实现)Javadocs。
# Stomp 入站通道适配器
StompInboundChannelAdapter
是一个一站式MessageProducer
组件,它将你的 Spring 集成应用程序订阅到所提供的 stomp 目的地,并从它们接收消息(通过在连接的StompSession
上使用所提供的MessageConverter
从 stomp 帧转换)。通过在StompInboundChannelAdapter
上使用适当的@ManagedOperation
注释,你可以在运行时更改目的地(因此也可以更改 stomp 订阅)。
有关更多配置选项,请参见Stomp 名称空间支持和StompInboundChannelAdapter
Javadoc (opens new window)。
# Stomp 出站通道适配器
StompMessageHandler
是MessageHandler
的MessageHandler
,用于将传出的Message<?>
实例通过destination
发送到 stompdestination
(在运行时通过 spel 表达式预先配置或确定)(由共享的StompSession
提供)。
有关更多配置选项,请参见Stomp 名称空间支持和StompMessageHandler
Javadoc (opens new window)。
# Stomp 标头映射
STOMP 协议提供头作为其框架的一部分。Stomp 框架的整个结构具有以下格式:
....
COMMAND
header1:value1
header2:value2
Body^@
....
Spring Framework 提供StompHeaders
来表示这些头。有关更多详细信息,请参见Javadoc (opens new window)。Stomp 帧被转换为和转换为Message<?>
实例,这些头被映射为和转换为MessageHeaders
实例。 Spring 集成为 Stomp 适配器提供了一个默认的HeaderMapper
实现。实现方式是StompHeaderMapper
。它分别为入站适配器和出站适配器提供fromHeaders()
和toHeaders()
操作。
与许多其他 Spring 集成模块一样,引入了IntegrationStompHeaders
类来将标准的 stomp 头映射到MessageHeaders
,并以stomp_
作为头名称前缀。此外,所有带有该前缀的MessageHeaders
实例在发送到目标时都映射到StompHeaders
。
有关更多信息,请参见Javadoc (opens new window)中的这些类和mapped-headers
属性描述。
# Stomp 集成事件
许多 STOMP 操作是异步的,包括错误处理。例如,Stomp 有一个RECEIPT
服务器帧,当客户端帧通过添加RECEIPT
头请求一个服务器帧时,它会返回这个服务器帧。为了提供对这些异步事件的访问, Spring 集成会发出StompIntegrationEvent
实例,你可以通过实现ApplicationListener
或使用<int-event:inbound-channel-adapter>
(参见Receiving Spring Application Events)来获得这些实例。
具体地说,当stompSessionListenableFuture
由于连接到 Stomp 代理失败而接收到onFailure()
时,从AbstractStompSessionManager
发出StompExceptionEvent
。另一个例子是StompMessageHandler
。它处理ERROR
stomp 帧,这些帧是服务器对此StompMessageHandler
发送的不正确(不接受)消息的响应。
在发送到StompSession
的消息的异步答案中,StompMessageHandler
发出StompReceiptEvent
作为StompSession.Receiptable
回调的一部分的StompReceiptEvent
。StompReceiptEvent
可以是正的,也可以是负的,这取决于RECEIPT
帧是否在receiptTimeLimit
期间从服务器接收,你可以在StompClientSupport
实例上配置该帧。它默认为15 * 1000
(以毫秒为单位,所以是 15 秒)。
只有当要发送的消息的RECEIPT stomp 报头不是null 时,才会添加StompSession.Receiptable 回调。你可以分别通过其 StompSession 选项和StompSessionManager 选项在StompSession 报头上启用自动RECEIPT 报头生成。 |
---|
有关如何配置 Spring 集成以接受那些ApplicationEvent
实例的详细信息,请参见Stomp 适配器 Java 配置。
# Stomp 适配器 Java 配置
下面的示例展示了用于 Stomp 适配器的全面的 Java 配置:
@Configuration
@EnableIntegration
public class StompConfiguration {
@Bean
public ReactorNettyTcpStompClient stompClient() {
ReactorNettyTcpStompClient stompClient = new ReactorNettyTcpStompClient("127.0.0.1", 61613);
stompClient.setMessageConverter(new PassThruMessageConverter());
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.afterPropertiesSet();
stompClient.setTaskScheduler(taskScheduler);
stompClient.setReceiptTimeLimit(5000);
return stompClient;
}
@Bean
public StompSessionManager stompSessionManager() {
ReactorNettyTcpStompSessionManager stompSessionManager = new ReactorNettyTcpStompSessionManager(stompClient());
stompSessionManager.setAutoReceipt(true);
return stompSessionManager;
}
@Bean
public PollableChannel stompInputChannel() {
return new QueueChannel();
}
@Bean
public StompInboundChannelAdapter stompInboundChannelAdapter() {
StompInboundChannelAdapter adapter =
new StompInboundChannelAdapter(stompSessionManager(), "/topic/myTopic");
adapter.setOutputChannel(stompInputChannel());
return adapter;
}
@Bean
@ServiceActivator(inputChannel = "stompOutputChannel")
public MessageHandler stompMessageHandler() {
StompMessageHandler handler = new StompMessageHandler(stompSessionManager());
handler.setDestination("/topic/myTopic");
return handler;
}
@Bean
public PollableChannel stompEvents() {
return new QueueChannel();
}
@Bean
public ApplicationListener<ApplicationEvent> stompEventListener() {
ApplicationEventListeningMessageProducer producer = new ApplicationEventListeningMessageProducer();
producer.setEventTypes(StompIntegrationEvent.class);
producer.setOutputChannel(stompEvents());
return producer;
}
}
# Stomp 名称空间支持
Spring 集成 Stomp 命名空间实现了入站和出站通道适配器组件。要将其包含在配置中,请在应用程序上下文配置文件中提供以下名称空间声明:
<?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-stomp="http://www.springframework.org/schema/integration/stomp"
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/stomp
https://www.springframework.org/schema/integration/stomp/spring-integration-stomp.xsd">
...
</beans>
# 理解<int-stomp:outbound-channel-adapter>
元素
下面的清单显示了 STOMP 出站通道适配器的可用属性:
<int-stomp:outbound-channel-adapter
id="" (1)
channel="" (2)
stomp-session-manager="" (3)
header-mapper="" (4)
mapped-headers="" (5)
destination="" (6)
destination-expression="" (7)
auto-startup="" (8)
phase=""/> (9)
1 | 组件 Bean 名.MessageHandler 的id 的 Bean 别名注册为id 加上.handler 。如果不设置 channel 属性,在应用程序上下文中创建并注册了一个DirectChannel ,并将这个id 属性的值作为 Bean 名称。在这种情况下,端点以 Bean 名称 id 加上.adapter 注册。 |
---|---|
2 | 如果id 存在,则标识连接到此适配器的通道。参见 id 。可选。 |
3 | 引用StompSessionManager Bean,它封装了低级连接和StompSession 处理操作。需要。 |
4 | 引用一个实现HeaderMapper<StompHeaders> 的 Bean,它将 Spring 集成MessageHeaders 映射到和从stomp 帧头映射。 它与 mapped-headers 是互斥的。它默认为 StompHeaderMapper 。 |
5 | 用逗号分隔的要映射到 Stomp 框架标头的 Stomp 标头的名称列表。 只能提供如果 header-mapper 引用未设置。此列表中的值也可以是简单的模式,以与标题名称进行匹配(例如 myheader* 或*myheader )。一个特殊的标记( STOMP_OUTBOUND_HEADERS )表示所有标准的 stomp 标题(内容长度、收据、心跳),它们是默认包含的。 如果你想添加自己的标头并希望同时映射标准标头,则必须包含该令牌或通过使用 header-mapper 提供自己的HeaderMapper 实现。 |
6 | STOMP 消息发送到的目的地的名称。 它与 destination-expression 是互斥的。 |
7 | 在运行时针对每个 Spring 积分Message 作为根对象求值的 SPEL 表达式。它与 destination 是互斥的。 |
8 | 布尔值,表示此端点是否应自动启动。 默认为 true 。 |
9 | 这个端点应该在其中开始和停止的生命周期阶段。 值越低,这个端点开始得越早,停止得越晚。 默认值是 Integer.MIN_VALUE 。值可以是负数。 参见[ SmartLifeCycle (https:/DOCS. Spring.io/ Spring/DOCS/current/javadoc-api/org/api/context/smartlifycle.html)。 |
# 理解<int-stomp:inbound-channel-adapter>
元素
下面的清单显示了 STOMP 入站通道适配器的可用属性:
<int-stomp:inbound-channel-adapter
id="" (1)
channel="" (2)
error-channel="" (3)
stomp-session-manager="" (4)
header-mapper="" (5)
mapped-headers="" (6)
destinations="" (7)
send-timeout="" (8)
payload-type="" (9)
auto-startup="" (10)
phase=""/> (11)
1 | 组件 Bean name. 如果不设置 channel 属性,将在应用程序上下文中创建并注册一个DirectChannel ,并将这个id 属性的值作为 Bean 名称。在这种情况下,端点以 Bean 名 id 加上.adapter 注册。 |
---|---|
2 | 标识连接到此适配器的通道。 |
3 | 应该发送ErrorMessage 实例的MessageChannel Bean 引用。 |
4 | 请参阅[<int-stomp:outbound-channel-adapter> ](#stomp-出站-通道-适配器)上的相同选项。 |
5 | 用逗号分隔的要从 stomp 帧头映射的 stomp 头的名称列表。 只有在 header-mapper 引用未设置的情况下,才能提供此选项。此列表中的值也可以是与头名称匹配的简单模式(例如, myheader* 或*myheader )。特殊令牌( STOMP_INBOUND_HEADERS )表示所有标准的 Stomp 标头(内容长度、收据、心跳等)。默认情况下,它们都包括在内。 如果你想添加自己的标头,并希望同时映射标准标头,你还必须包括这个令牌,或者使用 header-mapper 提供你自己的HeaderMapper 实现。 |
6 | 请参阅[<int-stomp:outbound-channel-adapter> ](#stomp-出站-通道-适配器)上的相同选项。 |
7 | 用逗号分隔的要订阅的目标名称列表。 可以在运行时通过 addDestination() 和removeDestination()``@ManagedOperation 注释修改目标(因此也是订阅)列表。 |
8 | 如果信道可以阻塞,则在向信道发送消息时等待的最大时间量(以毫秒为单位)。 例如,如果已达到其最大容量,则 QueueChannel 可以阻塞直到可用空间。 |
9 | 从传入的 Stomp 帧转换的目标payload 的完全限定的 Java 类型名称。它默认为 String.class 。 |
10 | 请参阅[<int-stomp:outbound-channel-adapter> ](#stomp-出站-通道-适配器)上的相同选项。 |
11 | 请参阅[<int-stomp:outbound-channel-adapter> ](#stomp-出站-通道-适配器)上的相同选项。 |