訊息流程
一旦 STOMP 端點被公開,Spring 應用程式就會成為連線用戶端的 STOMP Broker。本節描述伺服器端的訊息流程。
spring-messaging
模組包含對訊息應用程式的基礎支援,這些支援源自於 Spring Integration,後來被提取並整合到 Spring 框架中,以便在許多 Spring 專案和應用場景中更廣泛地使用。以下列表簡要描述了一些可用的訊息抽象概念
-
Message:訊息的簡單表示法,包括標頭和 Payload。
-
MessageHandler:用於處理訊息的契約。
-
MessageChannel:用於傳送訊息的契約,可實現生產者和消費者之間的鬆散耦合。
-
SubscribableChannel:具有
MessageHandler
訂閱者的MessageChannel
。 -
ExecutorSubscribableChannel:使用
Executor
傳遞訊息的SubscribableChannel
。
Java 組態(即 @EnableWebSocketMessageBroker
)和 XML Namespace 組態(即 <websocket:message-broker>
)都使用上述組件來組裝訊息工作流程。以下圖表顯示啟用簡單內建訊息 Broker 時使用的組件

上圖顯示了三個訊息通道
-
clientInboundChannel
:用於傳遞從 WebSocket 用戶端接收的訊息。 -
clientOutboundChannel
:用於將伺服器訊息傳送到 WebSocket 用戶端。 -
brokerChannel
:用於從伺服器端應用程式程式碼將訊息傳送到訊息 Broker。
下圖顯示了組態外部 Broker(例如 RabbitMQ)以管理訂閱和廣播訊息時使用的組件

前兩個圖表之間的主要區別在於使用「Broker Relay」透過 TCP 將訊息傳遞到外部 STOMP Broker,以及將訊息從 Broker 傳遞到已訂閱的用戶端。
當從 WebSocket 連線接收到訊息時,它們會被解碼為 STOMP Frame,轉換為 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 Frame 就開始在其上流動。 -
用戶端傳送具有
/topic/greeting
目的地標頭的 SUBSCRIBE Frame。一旦接收和解碼,訊息就會傳送到clientInboundChannel
,然後路由到訊息 Broker,訊息 Broker 會儲存用戶端訂閱。 -
用戶端傳送 SEND Frame 到
/app/greeting
。/app
前綴有助於將其路由到註解控制器。在剝離/app
前綴後,目的地的剩餘/greeting
部分會對應到GreetingController
中的@MessageMapping
方法。 -
從
GreetingController
傳回的值會轉換為 SpringMessage
,其 Payload 基於傳回值,預設目的地標頭為/topic/greeting
(從輸入目的地衍生,其中/app
被/topic
取代)。產生的訊息會傳送到brokerChannel
並由訊息 Broker 處理。 -
訊息 Broker 找到所有相符的訂閱者,並透過
clientOutboundChannel
將 MESSAGE Frame 傳送給每個訂閱者,訊息從那裡被編碼為 STOMP Frame 並在 WebSocket 連線上傳送。
下一節提供有關註解方法的更多詳細資訊,包括支援的引數和傳回值類型。