Skip to content

启用 STOMP

STOMP over WebSocket 的支持由 spring-messagingspring-websocket 模块提供。一旦引入了这些依赖,你就可以通过 WebSocket 暴露 STOMP 端点。

服务器端配置

通过实现 WebSocketMessageBrokerConfigurer 接口并添加 @EnableWebSocketMessageBroker 注解来开启功能:

java
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {

	@Override
	public void registerStompEndpoints(StompEndpointRegistry registry) {
		// /portfolio 是客户端进行 WebSocket 握手时连接的 HTTP URL
		registry.addEndpoint("/portfolio");
	}

	@Override
	public void configureMessageBroker(MessageBrokerRegistry config) {
		// 目的地以 /app 开头的消息将被路由到 @Controller 类中的 @MessageMapping 方法
		config.setApplicationDestinationPrefixes("/app");
		
		// 开启简单内存代理。目的地以 /topic 或 /queue 开头的消息将发送到代理
		config.enableSimpleBroker("/topic", "/queue");
	}
}
kotlin
@Configuration
@EnableWebSocketMessageBroker
class WebSocketConfiguration : WebSocketMessageBrokerConfigurer {

	override fun registerStompEndpoints(registry: StompEndpointRegistry) {
		// /portfolio 是客户端进行 WebSocket 握手时连接的 HTTP URL
		registry.addEndpoint("/portfolio")
	}

	override fun configureMessageBroker(config: MessageBrokerRegistry) {
		// 目的地以 /app 开头的消息将被路由到 @Controller 类中的 @MessageMapping 方法
		config.setApplicationDestinationPrefixes("/app")
		
		// 开启简单内存代理
		config.enableSimpleBroker("/topic", "/queue")
	}
}
xml
<websocket:message-broker application-destination-prefix="/app">
    <websocket:stomp-endpoint path="/portfolio" />
    <websocket:simple-broker prefix="/topic, /queue"/>
</websocket:message-broker>

TIP

对于内置的简单代理,/topic/queue 前缀没有特殊含义,仅作为区分发布-订阅与点对点消息的惯例。

客户端连接 (JavaScript)

推荐使用 stomp-js/stompjs 库:

javascript
const stompClient = new StompJs.Client({
	brokerURL: 'ws://domain.com/portfolio',
	onConnect: () => {
		console.log('连接成功!');
		// 订阅
		stompClient.subscribe('/topic/news', (message) => {
			console.log('收到消息:' + message.body);
		});
	}
});
stompClient.activate();

补充教学

1. setApplicationDestinationPrefixes 的作用

当你发送消息到 /app/hello 时,Spring 会分析出 /app 是应用前缀,然后把 /hello 交给对应 Controller 处理。如果不配置这个,所有消息都会直接飞到 Broker 代理手里,而不会经过你的 Java 业务代码。

2. 握手与连接的区别

在使用 STOMP 时,实际发生了两次“握手”:

  1. HTTP 握手: 客户端请求升级到 WebSocket。
  2. STOMP 连接: 在 WebSocket 通道开启后,客户端立即发送一个 CONNECT 帧,双方确认后状态才变为 CONNECTED

3. SockJS 回退

如果担心环境不支持 WebSocket,只需在配置中加上 .withSockJS()

java
registry.addEndpoint("/portfolio").withSockJS();

此时客户端也需要相应使用支持 SockJS 的库进行连接。

Based on Spring Framework.