消息流
一旦暴露了 STOMP 端点,Spring 应用程序就会成为已连接客户端的 STOMP 代理。本节描述服务器端的消息流。
spring-messaging 模块包含了对消息传递应用程序的基础支持。以下是几个核心抽象:
- Message: 消息的简单表示,包括标头 (Headers) 和负载 (Payload)。
- MessageHandler: 处理消息的契约。
- MessageChannel: 发送消息的契约,实现生产者和消费者之间的解耦。
- SubscribableChannel: 带有
MessageHandler订阅者的MessageChannel。 - ExecutorSubscribableChannel: 使用
Executor交付消息的SubscribableChannel。
频道 (Channels) 与流程
无论通过 Java 配置还是 XML 配置,Spring 都会组装一个消息工作流。以下是启用简单内置消息代理(Simple Broker)时的组件示意:

图中包含三个核心消息频道:
- clientInboundChannel: 接收从 WebSocket 客户端发来的消息。
- clientOutboundChannel: 向 WebSocket 客户端发送服务器消息。
- brokerChannel: 用于从服务器端应用程序代码内部向消息代理发送消息。
当使用外部代理(如 RabbitMQ)时,流程如下:

主要的区别在于使用了“代理中继”(Broker Relay),它通过 TCP 将消息传递给外部 STOMP 代理,并将来自代理的消息传递给已订阅的客户端。
典型流程轨迹
- 接收消息: 从 WebSocket 连接接收到的消息被解码为 STOMP 帧,转为 Spring
Message表示,发送到clientInboundChannel。 - 路由方法: 目的地以
/app开头的 STOMP 消息被路由到@MessageMapping控制器方法。 - 路由代理: 目的地以
/topic或/queue开头的消息直接路由到消息代理。 - 返回结果: 控制器方法返回的值变为
Message发送到brokerChannel,代理再通过clientOutboundChannel广播给匹配的订阅者。
补充教学
1. 这种架构的意义:解耦
Spring 将 WebSocket 原始连接与业务处理完全解耦。你的 Controller 处理的是标准的 Message 对象,并不需要知道它是从哪个物理连接、哪个 TCP 端口过来的。这种抽象使得同样的逻辑也可以应用于非 WebSocket 环境。
2. 拦截器 (Interceptors)
由于一切都流经 MessageChannel,你可以在这些频道上注册 ChannelInterceptor。例如,在 clientInboundChannel 上加一个拦截器,就可以在消息到达 Controller 之前进行统一的权限控制或日志记录。
3. 多线程处理
ExecutorSubscribableChannel 意味着消息的处理是异步的。Spring 默认配置了线程池来处理这些频道,这意味着高并发下的消息发送不会阻塞 Servlet 容器的主线程。