带注解的控制器
应用程序可以使用带有注解的 @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。