消息流
一旦 STOMP 端点被暴露,Spring 应用程序就成为了连接客户端的 STOMP 代理。本节描述服务器端的消息流。
spring-messaging
模块包含对消息应用程序的基础支持,这些支持起源于 Spring Integration,后来被提取并整合到 Spring 框架中,以便在许多 Spring 项目和应用程序场景中广泛使用。
以下列表简要描述了一些可用的消息抽象:
-
Message: 消息的简单表示,包括头部和载荷。
-
MessageHandler: 处理消息的契约。
-
MessageChannel: 发送消息的契约,实现了生产者和消费者之间的松散耦合。
-
SubscribableChannel: 具有
MessageHandler
订阅者的MessageChannel
。 -
ExecutorSubscribableChannel: 使用
Executor
传递消息的SubscribableChannel
。
Java 配置(即 @EnableWebSocketMessageBroker
)和 XML 命名空间配置(即 <websocket:message-broker>
)都使用上述组件来组装消息工作流。
下图显示了启用简单内置消息代理时使用的组件:

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

前面两张图之间的主要区别在于使用了“代理中继
”来通过 TCP 将消息传递给外部 STOMP 代理,以及将消息从代理传递给订阅的客户端。
当从 WebSocket 连接接收到消息时,它们被解码为 STOMP 帧,转换为 Spring Message
表示,并发送到 clientInboundChannel
进行进一步处理。
例如,目的地头部以 /app
开头的 STOMP 消息可能会被路由到注解控制器中的 @MessageMapping
方法,而 /topic
和 /queue
消息可能会直接路由到消息代理。
处理来自客户端的 STOMP 消息的注解 @Controller
可以通过 brokerChannel
向消息代理发送消息,然后代理通过 clientOutboundChannel
将消息广播给匹配的订阅者。
同一个控制器也可以响应 HTTP 请求执行相同的操作,因此客户端可以执行 HTTP POST,然后 @PostMapping
方法可以向消息代理发送消息以广播给订阅的客户端。
我们可以通过一个简单的例子来追踪消息流。考虑以下设置服务器的例子:
上述示例支持以下流程:
-
客户端连接到
http://localhost:8080/portfolio
,一旦 WebSocket 连接建立,STOMP 帧就开始在其上传输。 -
客户端发送一个 SUBSCRIBE 帧,其目的地头部为
/topic/greeting
。收到并解码后,消息被发送到clientInboundChannel
,然后路由到消息代理,消息代理存储客户端订阅。 -
客户端向
/app/greeting
发送一个 SEND 帧。/app
前缀有助于将其路由到注解控制器。在剥离/app
前缀后,目的地中剩余的/greeting
部分被映射到GreetingController
中的@MessageMapping
方法。 -
从
GreetingController
返回的值被转换为一个 SpringMessage
,其载荷基于返回值,默认目的地头部为/topic/greeting
(从输入目的地派生,其中/app
被/topic
替换)。生成的消息被发送到brokerChannel
并由消息代理处理。 -
消息代理找到所有匹配的订阅者,并通过
clientOutboundChannel
向每个订阅者发送一个 MESSAGE 帧,消息从那里被编码为 STOMP 帧并发送到 WebSocket 连接。
下一节将提供有关注解方法的更多详细信息,包括支持的参数类型和返回值。