Skip to content

带注解的控制器

应用程序可以使用带有注解的 @Controller 类来处理来自客户端的消息。

@MessageMapping

@MessageMapping 用于根据消息的目的地 (Destination) 将消息路由到对应方法。它支持方法级别和类级别。在类级别使用时,定义的映射会共享给该控制器内的所有方法。

默认采用 Ant 风格的路径模式(如 /thing*),支持变量占位符(如 /thing/{id})。

支持的方法参数

参数类型描述
Message访问完整的消息对象。
MessageHeaders访问消息内的标头。
StompHeaderAccessor通过类型化的访问器方法访问标头(如获取 SessionId)。
@Payload访问消息负载,由配置的转换器(如 Jackson)转换。
@Header访问特定的标头值。
@DestinationVariable访问从目的地中提取的模板变量。
java.security.Principal反映 WebSocket 握手时的用户信息。

返回值

默认情况下,@MessageMapping 方法的返回值会被序列化并作为消息发送到 brokerChannel,目的地与输入目的地相同,但前缀替换为 /topic(即广播给其他订阅者)。

你可以使用 @SendTo@SendToUser 来自定义输出目的地:

  • @SendTo: 自定义目标路径或指定多个目的地。
  • @SendToUser: 仅将消息发送给发起请求的那个特定用户。

@SubscribeMapping

@SubscribeMapping 仅针对订阅(SUBSCRIBE)消息。与 @MessageMapping 的区别在于:

  • 默认行为: 消息直接通过 clientOutboundChannel 发回给订阅的客户端(一对一响应),不经过代理广播
  • 用途: 非常适合在客户端订阅时立即返回一份“初始化数据”,而不是让它干等着之后的广播。

@MessageExceptionHandler

用于处理 @MessageMapping 方法中抛出的异常。类似于 Spring MVC 的 @ExceptionHandler,你可以定义在 Controller 内部,或者通过 @ControllerAdvice 定义全局的异常处理。


补充教学

1. 目的地变量的妙用

通过 @DestinationVariable,你可以轻松实现动态房间逻辑:

java
@MessageMapping("/chat.{roomId}")
public void handleChat(@DestinationVariable String roomId, Message message) {
    // 处理进入 roomId 房间的消息
}

2. 校验负载

你可以像在 Web MVC 中一样使用 @Valid@Validated

java
@MessageMapping("/send")
public void handle(@Payload @Valid MyData data) { ... }

如果校验失败,异常会被路由到异常处理器。

3. @SendToUser 的工作原理

它通过特殊的 /user/ 前缀机制工作。即使多个用户在一个连接上,Spring 也能识别出 Principal 身份,并确保消息只投递给对应的 Session。

Based on Spring Framework.