訊息流
一旦暴露 STOMP 端點,Spring 應用程式就成為連線客戶端的 STOMP broker。本節描述了伺服器端的訊息流。
spring-messaging
模組包含訊息應用程式的基礎支援,它起源於 Spring Integration,後來被提取並納入 Spring Framework 中,以便在許多 Spring 專案和應用程式場景中更廣泛地使用。以下列表簡要描述了一些可用的訊息抽象
-
Message:訊息的簡單表示,包含頭部和載荷。
-
MessageHandler:處理訊息的契約。
-
MessageChannel:傳送訊息的契約,可以在生產者和消費者之間實現松耦合。
-
SubscribableChannel:帶有
MessageHandler
訂閱者的MessageChannel
。 -
ExecutorSubscribableChannel:使用
Executor
傳遞訊息的SubscribableChannel
。
Java 配置(即 @EnableWebSocketMessageBroker
)和 XML 名稱空間配置(即 <websocket:message-broker>
)都使用上述元件來組裝訊息工作流。下圖顯示了啟用簡單內建訊息 broker 時使用的元件

上圖顯示了三個訊息通道
-
clientInboundChannel
:用於傳遞從 WebSocket 客戶端接收的訊息。 -
clientOutboundChannel
:用於向 WebSocket 客戶端傳送伺服器訊息。 -
brokerChannel
:用於在伺服器端應用程式程式碼中向訊息 broker 傳送訊息。
下圖顯示了配置外部 broker(例如 RabbitMQ)用於管理訂閱和廣播訊息時使用的元件

前兩個圖的主要區別在於使用“broker 中繼”透過 TCP 將訊息傳遞到外部 STOMP broker,以及將訊息從 broker 傳遞給訂閱的客戶端。
當從 WebSocket 連線接收到訊息時,它們被解碼為 STOMP 幀,轉換為 Spring Message
表示形式,併發送到 clientInboundChannel
進行進一步處理。例如,目的地頭部以 /app
開頭的 STOMP 訊息可以路由到註解控制器的 @MessageMapping
方法,而 /topic
和 /queue
訊息可以直接路由到訊息 broker。
處理來自客戶端的 STOMP 訊息的註解 @Controller
可以透過 brokerChannel
向訊息 broker 傳送訊息,然後 broker 透過 clientOutboundChannel
將訊息廣播給匹配的訂閱者。同一個控制器也可以響應 HTTP 請求執行相同的操作,因此客戶端可以執行 HTTP POST,然後 @PostMapping
方法可以將訊息傳送到訊息 broker,以廣播給訂閱的客戶端。
我們可以透過一個簡單的示例來追蹤流程。考慮以下示例,它設定了一個伺服器
-
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 幀就開始在其上傳輸。 -
客戶端傳送一個 SUBSCRIBE 幀,其目的地頭部為
/topic/greeting
。收到並解碼後,訊息傳送到clientInboundChannel
,然後路由到訊息 broker,由其儲存客戶端訂閱資訊。 -
客戶端向
/app/greeting
傳送一個 SEND 幀。/app
字首有助於將其路由到註解控制器。移除/app
字首後,目的地剩餘的/greeting
部分對映到GreetingController
中的@MessageMapping
方法。 -
GreetingController
返回的值被轉換為一個 SpringMessage
,其載荷基於返回值,預設目的地頭部為/topic/greeting
(從輸入目的地中將/app
替換為/topic
派生而來)。生成的訊息被髮送到brokerChannel
並由訊息 broker 處理。 -
訊息 broker 查詢所有匹配的訂閱者,並透過
clientOutboundChannel
向每個訂閱者傳送一個 MESSAGE 幀,訊息從clientOutboundChannel
被編碼為 STOMP 幀並在 WebSocket 連線上傳輸。
下一節將提供更多關於註解方法的詳細資訊,包括支援的引數型別和返回值。