如何使用指定用户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 );
}