Flow of Messages
公开 STOMP 端点后,Spring 应用程序会为连接的客户端成为 STOMP 代理。本部分介绍服务器端的邮件流。
Once a STOMP endpoint is exposed, the Spring application becomes a STOMP broker for connected clients. This section describes the flow of messages on the server side.
`spring-messaging`模块包含对源自 Spring Integration的消息传递应用程序的基本支持,后来被提取出来并合并到 Spring 框架中,以便在许多https://spring.io/projects[Spring 项目]和应用程序场景中更广泛地使用。以下列表简要描述了几个可用的消息传递抽象:
The spring-messaging
module contains foundational support for messaging applications
that originated in Spring Integration and was
later extracted and incorporated into the Spring Framework for broader use across many
Spring projects and application scenarios.
The following list briefly describes a few of the available messaging abstractions:
-
Message: Simple representation for a message, including headers and payload.
-
MessageHandler: Contract for handling a message.
-
MessageChannel: Contract for sending a message that enables loose coupling between producers and consumers.
-
SubscribableChannel:
MessageChannel
withMessageHandler
subscribers. -
ExecutorSubscribableChannel:
SubscribableChannel
that uses anExecutor
for delivering messages.
Java 配置(即 @EnableWebSocketMessageBroker
)和 XML 命名空间配置(即 <websocket:message-broker>
)都使用前述组件来组合消息工作流。以下示意图显示了启用简单内置消息代理时所用的组件:
Both the Java configuration (that is, @EnableWebSocketMessageBroker
) and the XML namespace configuration
(that is, <websocket:message-broker>
) use the preceding components to assemble a message
workflow. The following diagram shows the components used when the simple built-in message
broker is enabled:
上述示意图显示了三个消息通道:
The preceding diagram shows three message channels:
-
clientInboundChannel
: For passing messages received from WebSocket clients. -
clientOutboundChannel
: For sending server messages to WebSocket clients. -
brokerChannel
: For sending messages to the message broker from within server-side application code.
下一张示意图显示了针对管理订阅和广播消息而配置的外部代理(例如 RabbitMQ)时所用的组件:
The next diagram shows the components used when an external broker (such as RabbitMQ) is configured for managing subscriptions and broadcasting messages:
两个前述示意图之间的主要区别在于,使用“broker relay
”将消息通过 TCP 传递至外部 STOMP 代理,和将消息从代理传递至已订阅的客户端。
The main difference between the two preceding diagrams is the use of the “broker relay” for passing messages up to the external STOMP broker over TCP and for passing messages down from the broker to subscribed clients.
从 WebSocket 连接接收消息后,这些消息会被解码成 STOMP 帧,转换成 Spring Message
表示形式,并发送至 clientInboundChannel
以作进一步处理。例如,目标头以 /app
开头的 STOMP 消息可能会路由至带注释控制器的 @MessageMapping
方法,而 /topic
和 /queue
消息可能会直接路由至消息代理。
When messages are received from a WebSocket connection, they are decoded to STOMP frames,
turned into a Spring Message
representation, and sent to the
clientInboundChannel
for further processing. For example, STOMP messages whose
destination headers start with /app
may be routed to @MessageMapping
methods in
annotated controllers, while /topic
and /queue
messages may be routed directly
to the message broker.
处理来自客户端的 STOMP 消息的带注释 @Controller
可能会通过 brokerChannel
向消息代理发送消息,而代理会通过 clientOutboundChannel
将消息广播至相匹配的订阅方。同样的控制器也可在响应 HTTP 请求时执行相同的操作,因此,客户端可以执行 HTTP POST,然后 @PostMapping
方法可向消息代理发送消息,以便广播至已订阅的客户端。
An annotated @Controller
that handles a STOMP message from a client may send a message to
the message broker through the brokerChannel
, and the broker broadcasts the
message to matching subscribers through the clientOutboundChannel
. The same
controller can also do the same in response to HTTP requests, so a client can perform an
HTTP POST, and then a @PostMapping
method can send a message to the message broker
to broadcast to subscribed clients.
我们可以通过一个简单的例子来跟踪流程。考虑一下以下设置一个服务器的例子:
We can trace the flow through a simple example. Consider the following example, which sets up a server:
-
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())
}
}
前面的例子支持以下流程:
The preceding example supports the following flow:
-
The client connects to
http://localhost:8080/portfolio
and, once a WebSocket connection is established, STOMP frames begin to flow on it. -
The client sends a SUBSCRIBE frame with a destination header of
/topic/greeting
. Once received and decoded, the message is sent to theclientInboundChannel
and is then routed to the message broker, which stores the client subscription. -
The client sends a SEND frame to
/app/greeting
. The/app
prefix helps to route it to annotated controllers. After the/app
prefix is stripped, the remaining/greeting
part of the destination is mapped to the@MessageMapping
method inGreetingController
. -
The value returned from
GreetingController
is turned into a SpringMessage
with a payload based on the return value and a default destination header of/topic/greeting
(derived from the input destination with/app
replaced by/topic
). The resulting message is sent to thebrokerChannel
and handled by the message broker. -
The message broker finds all matching subscribers and sends a MESSAGE frame to each one through the
clientOutboundChannel
, from where messages are encoded as STOMP frames and sent on the WebSocket connection.
下一部分提供关于注释方法的更多详细信息,包括支持的参数类型和返回值。
The next section provides more details on annotated methods, including the kinds of arguments and return values that are supported.