[英]Spring webflux websocket - Multiple rooms chat
我目前正在使用 spring 反应构建一个聊天应用程序。
每个用户都可以是多个聊天室的一部分。
我试图只将每条聊天消息发送给连接到相应房间的客户端。
例如,如果用户在聊天室中发送一条 UUID 为“32e4adff-d0bd-4496-ae40-0e799eeb5fe7”的消息,则只有连接到端点为“/chat/32e4adff-d0bd-4496-ae40-0e799eeb5fe7”的套接字的客户端才会接收消息。
目前,我的 websocket 处理程序映射是:
@Bean
public HandlerMapping webSocketHandlerMapping() {
String path = "/chat/*";
Map<String, WebSocketHandler> map = Map.of(path, webSocketHandler);
return new SimpleUrlHandlerMapping(map, -1);
}
还有我的 ChatSocketHandler :
@Component
public class ChatSocketHandler implements WebSocketHandler {
private final ObjectMapper mapper = new ObjectMapper();
private Sinks.Many<ChatMessage> sinks = Sinks.many().multicast().directBestEffort();
private Flux<ChatMessage> flux = sinks.asFlux();
private final Sinks.EmitFailureHandler emitFailureHandler =
(signalType, emitResult) -> emitResult.equals(Sinks.EmitResult.FAIL_NON_SERIALIZED);
private final ChatService chatService;
@Autowired
public ChatSocketHandler(ChatService chatService) {
this.chatService = chatService;
}
@Override
public Mono<Void> handle(WebSocketSession session) {
// TODO get rid of subscribe
session
.receive()
.map(
webSocketMessage -> {
try {
return mapper.readValue(webSocketMessage.getPayloadAsText(), ChatMessage.class);
} catch (JsonProcessingException e) {
e.printStackTrace();
return new ChatMessage();
}
})
.flatMap(chatService::sendMessage)
.subscribe(webSocketMessage -> sinks.emitNext(webSocketMessage, emitFailureHandler));
return session.send(
Mono.delay(Duration.ofMillis(100))
.thenMany(flux.map(it -> session.textMessage(toJson(it)))));
}
private String toJson(ChatMessage object) {
try {
return mapper.writeValueAsString(object);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
}
和聊天服务功能发送消息:
public Mono<ChatMessage> sendMessage(ChatMessage chatMessage) {
return chatMessageRepository.insert(chatMessage);
}
目前,客户端会收到所有房间的消息,即使是他们不应该连接的房间。
如何配置我的 websocket 以便只有连接到房间的用户才能收到那里发布的消息?
我通过在 session.send 中添加过滤器来修复它
@Override
public Mono<Void> handle(WebSocketSession session) {
String path = session.getHandshakeInfo().getUri().getPath();
String chatId = path.substring(path.lastIndexOf('/') + 1);
session
.receive()
.map(
webSocketMessage -> {
try {
return mapper.readValue(webSocketMessage.getPayloadAsText(), ChatMessage.class);
} catch (JsonProcessingException e) {
e.printStackTrace();
return new ChatMessage();
}
})
.flatMap(chatService::sendMessage)
.subscribe(webSocketMessage -> sinks.emitNext(webSocketMessage, emitFailureHandler));
return session.send(
Mono.delay(Duration.ofMillis(100))
.thenMany(
flux.filter(it -> chatId.equals(it.getChatId()))
.map(it -> session.textMessage(toJson(it)))));
}
我不确定是否有更好的方法来做到这一点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.