消息流
一旦 STOMP 端点被公开,Spring 应用程序就会成为 STOMP 代理 连接的客户端。本节介绍服务器端的消息流。
这spring-messaging
模块包含对消息传递应用程序的基本支持
它源自 Spring Integration,并且是
后来提取并合并到 Spring 框架中,以便在许多 Spring 项目和应用程序场景中更广泛地使用。
以下列表简要介绍了一些可用的消息传递抽象:
-
消息: 消息的简单表示形式,包括 Headers 和 payload。
-
MessageHandler 中: 用于处理消息的协定。
-
MessageChannel 中: 用于发送支持生产者和使用者之间松散耦合的消息的 Contract。
-
SubscribableChannel 的
MessageChannel
跟MessageHandler
用户。 -
ExecutorSubscribableChannel 中:
SubscribableChannel
它使用Executor
用于传递消息。
Java 配置(即@EnableWebSocketMessageBroker
) 和 XML 命名空间配置
(即<websocket:message-broker>
) 使用上述组件来组合消息
工作流。下图显示了 simple 内置消息
broker 已启用:

上图显示了三个消息通道:
-
clientInboundChannel
:用于传递从 WebSocket 客户端接收的消息。 -
clientOutboundChannel
:用于向 WebSocket 客户端发送服务器消息。 -
brokerChannel
:用于从内部向消息代理发送消息 服务器端应用程序代码。
下图显示了外部代理(例如 RabbitMQ) 配置为管理订阅和广播消息:

前面两个图之间的主要区别在于使用 “broker relay” 来传递 消息通过 TCP 传输到外部 STOMP 代理,并用于从 broker 添加到订阅的客户端。
当从 WebSocket 连接接收到消息时,它们被解码为 STOMP 帧。
变成了弹簧Message
表示形式,并发送到clientInboundChannel
以便进一步处理。例如,其 STOMP 消息
目标标头开头为/app
可以路由到@MessageMapping
methods 中的
注解的控制器,而/topic
和/queue
消息可以直接路由
发送到消息代理。
带注释的@Controller
处理来自客户端的 STOMP 消息的 STOMP 消息可能会将消息发送到
消息代理通过brokerChannel
,并且代理会广播
消息通过clientOutboundChannel
.一样
controller 也可以执行相同的作来响应 HTTP 请求,因此客户端可以执行
HTTP POST,然后是@PostMapping
方法可以向消息代理发送消息
向订阅的客户端广播。
我们可以通过一个简单的例子来追踪流程。请考虑以下示例,该示例设置了一个服务器:
-
Java
-
Kotlin
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/portfolio");
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.setApplicationDestinationPrefixes("/app");
registry.enableSimpleBroker("/topic");
}
}
@Configuration
@EnableWebSocketMessageBroker
class WebSocketConfiguration : WebSocketMessageBrokerConfigurer {
override fun registerStompEndpoints(registry: StompEndpointRegistry) {
registry.addEndpoint("/portfolio")
}
override fun configureMessageBroker(registry: MessageBrokerRegistry) {
registry.setApplicationDestinationPrefixes("/app")
registry.enableSimpleBroker("/topic")
}
}
-
Java
-
Kotlin
@Controller
public class GreetingController {
@MessageMapping("/greeting")
public String handle(String greeting) {
return "[" + getTimestamp() + ": " + greeting;
}
private String getTimestamp() {
return new SimpleDateFormat("MM/dd/yyyy h:mm:ss a").format(new Date());
}
}
@Controller
class GreetingController {
@MessageMapping("/greeting")
fun handle(greeting: String): String {
return "[${getTimestamp()}: $greeting"
}
private fun getTimestamp(): String {
return SimpleDateFormat("MM/dd/yyyy h:mm:ss a").format(Date())
}
}
前面的示例支持以程:
-
客户端连接到
localhost:8080/portfolio
并且,一旦 WebSocket 连接 建立,STOMP 帧开始在其上流动。 -
客户端发送目标标头为
/topic/greeting
.一旦收到 并解码后,消息将发送到clientInboundChannel
,然后路由到 Message Broker,用于存储客户端订阅。 -
客户端将 SEND 帧发送到
/app/greeting
.这/app
prefix 有助于将其路由到 带注释的控制器。在/app
前缀被剥离,则剩余的/greeting
部分目标映射到@MessageMapping
method 中GreetingController
. -
从
GreetingController
变成弹簧Message
跟 基于返回值和默认目标标头/topic/greeting
(从 input destination 派生自/app
替换为/topic
).生成的消息将发送到brokerChannel
并处理 由 Message Broker 提供。 -
消息代理查找所有匹配的订阅者,并向每个订阅者发送一个 MESSAGE 帧 通过
clientOutboundChannel
,从中消息编码为 STOMP 帧 并通过 WebSocket 连接发送。
下一节将提供有关带注释方法的更多详细信息,包括 支持的参数和返回值的种类。