Как передать сообщение контроллеру с помощью @MessageMapping с указанным URL-адресом пользователя? - PullRequest
0 голосов
/ 17 июня 2020

У меня такая проблема. Когда я пытаюсь отправить сообщение со стороны клиента на сервер, оно не соответствует моим методам @ MessageMapping . Я не знаю, как перехватывать сообщения на уровне контроллера.

Клиентская сторона отправляет сообщение (это реакция-топт, который использует sock js):

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());
    }

}

Я также добавил класс перехватчика для проверки пути входящего сообщения:

public class MyChannelInterceptor implements ChannelInterceptor {

    @Override
    public Message<?> preSend(Message<?> message, MessageChannel channel) {
        StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
        return message;
    }
}

При отладке MyChannelInterceptor я вижу сообщение с полезной нагрузкой и заголовками. Есть заголовок simpDestination с таким значением:

/user/baedde36-0f9e-4fa5-b8d7-687db1dbcd67/queue/move

Какое значение @MessageMapping я должен написать для обработки сообщений от указанных пользователей? Это сообщение успешно попадает на фронт по подписке на этот топи c, но не остается ни на одном контроллере:

`/user/${message}/queue/move`

Я просто хочу обрабатывать сообщения на стороне сервера, но не могу его там поймать.

1 Ответ

0 голосов
/ 18 июня 2020

Хорошо. Как я понял, есть 3 способа обработки сообщений websocket:

/app - handles with controller
/user - handles with broker, sends messages to specific users
/topic - broadcast to topic for all subscribers

В моей ситуации мне просто нужно создать объект json с userId, ReceiverId и message. На стороне сервера добавьте класс DTO и получите его как атрибут в моем методе контроллера.

Решение:

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;
}

Класс контроллера:

@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 );
}
...