如何使用指定用户url通过@MessageMapping 将消息传递给控制器?
How to pass message to controller by @MessageMapping with specified user url?
我有这样的问题。当我尝试从客户端向服务器发送消息时,它与我的 @MessageMapping 方法不匹配。不知道怎么拦截controller层的消息
客户端
发送消息(使用 sockjs 的 react-stomp):
move = (move) => {
this.clientRef.sendMessage("/user/${this.state.opponentId}/queue/move", JSON.stringify(move))
};
服务器端。 WebSocketConfig:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/handler")
.setHandshakeHandler(new CustomHandshakeHandler())
.setAllowedOrigins("http://localhost:3000")
.withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry brokerRegistry) {
brokerRegistry.setApplicationDestinationPrefixes("/app");
brokerRegistry.enableSimpleBroker("/topic", "/queue", "/user");
}
@EventListener
void handleSessionConnectedEvent(SessionConnectedEvent event) {
StompHeaderAccessor sha = StompHeaderAccessor.wrap(event.getMessage());
}
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.interceptors(new MyChannelInterceptor());
}
}
我还添加了拦截器 class 来检查传入消息的路径:
public class MyChannelInterceptor implements ChannelInterceptor {
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
return message;
}
}
在调试 MyChannelInterceptor 时,我看到带有负载和 headers 的消息。有 simpDestination header 具有这样的值:
/user/baedde36-0f9e-4fa5-b8d7-687db1dbcd67/queue/move
我应该写什么@MessageMapping 值来处理来自指定用户的消息?此消息通过订阅此主题成功到达前端,但不会保留在任何控制器上:
`/user/${message}/queue/move`
我只想在服务器端处理消息,但无法在服务器端处理消息。
好的。据我了解,有 3 种方法可以处理 websocket 消息:
/app - handles with controller
/user - handles with broker, sends messages to specific users
/topic - broadcast to topic for all subscribers
在我的情况下,我只需要用 userId、receiverId 和消息创建 json 对象。在服务器端添加 DTO class 并将其作为属性获取到我的控制器方法中。
解决方案:
move = (move) => {
let moveDto = {move: move, userId: this.state.userId, opponentId: this.state.opponentId}
this.clientRef.sendMessage(`/app/move`, JSON.stringify(moveDto))
};
服务器端:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MoveDto {
private String userId;
private String opponentId;
private int move;
}
控制器class:
@RestController
public class GameController {
@Autowired
private SimpMessagingTemplate simpMessagingTemplate;
...//some code here
@MessageMapping("/move")
public void message(MoveDto moveDto) {
String userMessage= "foo";
String opponentMessage = "bar";
simpMessagingTemplate.convertAndSendToUser(
moveDto.getUserId(), "/queue/message", userMessage);
simpMessagingTemplate.convertAndSendToUser(
moveDto.getOpponentId(), "/queue/message", opponentMessage );
}
我有这样的问题。当我尝试从客户端向服务器发送消息时,它与我的 @MessageMapping 方法不匹配。不知道怎么拦截controller层的消息
客户端 发送消息(使用 sockjs 的 react-stomp):
move = (move) => {
this.clientRef.sendMessage("/user/${this.state.opponentId}/queue/move", JSON.stringify(move))
};
服务器端。 WebSocketConfig:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/handler")
.setHandshakeHandler(new CustomHandshakeHandler())
.setAllowedOrigins("http://localhost:3000")
.withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry brokerRegistry) {
brokerRegistry.setApplicationDestinationPrefixes("/app");
brokerRegistry.enableSimpleBroker("/topic", "/queue", "/user");
}
@EventListener
void handleSessionConnectedEvent(SessionConnectedEvent event) {
StompHeaderAccessor sha = StompHeaderAccessor.wrap(event.getMessage());
}
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.interceptors(new MyChannelInterceptor());
}
}
我还添加了拦截器 class 来检查传入消息的路径:
public class MyChannelInterceptor implements ChannelInterceptor {
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
return message;
}
}
在调试 MyChannelInterceptor 时,我看到带有负载和 headers 的消息。有 simpDestination header 具有这样的值:
/user/baedde36-0f9e-4fa5-b8d7-687db1dbcd67/queue/move
我应该写什么@MessageMapping 值来处理来自指定用户的消息?此消息通过订阅此主题成功到达前端,但不会保留在任何控制器上:
`/user/${message}/queue/move`
我只想在服务器端处理消息,但无法在服务器端处理消息。
好的。据我了解,有 3 种方法可以处理 websocket 消息:
/app - handles with controller
/user - handles with broker, sends messages to specific users
/topic - broadcast to topic for all subscribers
在我的情况下,我只需要用 userId、receiverId 和消息创建 json 对象。在服务器端添加 DTO class 并将其作为属性获取到我的控制器方法中。
解决方案:
move = (move) => {
let moveDto = {move: move, userId: this.state.userId, opponentId: this.state.opponentId}
this.clientRef.sendMessage(`/app/move`, JSON.stringify(moveDto))
};
服务器端:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class MoveDto {
private String userId;
private String opponentId;
private int move;
}
控制器class:
@RestController
public class GameController {
@Autowired
private SimpMessagingTemplate simpMessagingTemplate;
...//some code here
@MessageMapping("/move")
public void message(MoveDto moveDto) {
String userMessage= "foo";
String opponentMessage = "bar";
simpMessagingTemplate.convertAndSendToUser(
moveDto.getUserId(), "/queue/message", userMessage);
simpMessagingTemplate.convertAndSendToUser(
moveDto.getOpponentId(), "/queue/message", opponentMessage );
}