You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WebSocket与MongoDB集成时GenericMessage处理失败问题排查

问题描述

我开发了一个支持多用户输入、单个终端用户接收所有消息的简易聊天服务,编写了以下相关类和配置,运行后Spring Boot抛出错误,且MongoDB未生成预期集合,浏览器控制台仅显示订阅日志无报错。


后端代码

ChatUserService 类

@Service
public class ChatUserService {

    private final ChatUserRepository chatUserRepository;

    @Autowired
    public ChatUserService(ChatUserRepository chatUserRepository) {
        this.chatUserRepository = chatUserRepository;
    }

    public void saveChatUser(ChatUser chatUser){
        chatUser.setStatus(Status.ONLINE);
        chatUserRepository.save(chatUser);
    }
    public void disconnect(ChatUser chatUser){
        var connectedChatUser = chatUserRepository.findById(chatUser.getEmail())
                .orElse(null);
        if(connectedChatUser != null){
            connectedChatUser.setStatus(Status.OFFLINE);
            chatUserRepository.save(connectedChatUser);
        }

    }
    public List<ChatUser> findConnectedChatUsers(){
        return chatUserRepository.findAllByStatus(Status.ONLINE);
    }
}

UserController 类

@Controller
public class UserController {
    private final ChatUserService chatUserService;

@Autowired
public UserController(ChatUserService chatUserService) {
    this.chatUserService = chatUserService;
}

@MessageMapping("user.addUser")
@SendTo("/user/topic") 
public ChatUser addUser(@Payload ChatUser chatUser){
    chatUserService.saveChatUser(chatUser);
    return chatUser;
}

WebSocket 配置类

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableSimpleBroker("/user");
        registry.setApplicationDestinationPrefixes("/app");
        registry.setUserDestinationPrefix("/user");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws").withSockJS();
    }

    @Override
    public boolean configureMessageConverters(List<MessageConverter> messageConverters) {
        var resolver = new DefaultContentTypeResolver();
        resolver.setDefaultMimeType(MimeTypeUtils.APPLICATION_JSON);
        var converter = new MappingJackson2MessageConverter();
        converter.setObjectMapper(new ObjectMapper());
        converter.setContentTypeResolver(resolver);
        messageConverters.add(converter);
        return false;
    }
}

客户端代码

async function connect(event){
        email = await fetchAdminEmail()
        const socket = new SockJS('/ws');
        stompClient = Stomp.over(socket);
        stompClient.connect({},onConnected,onError);
        event.preventDefault();
    }
    function onConnected() {
        stompClient.subscribe(`/user/${email}/queue/messages`, onMessageReceived);
        stompClient.subscribe(`/user/public`, onMessageReceived); 
        stompClient.send('/app/user.addUser',
            {},
            JSON.stringify({email: email,status:'ONLINE'})
        ); 
        findAndDisplayConnectedUsers().then();
    }
    async function findAndDisplayConnectedUsers(){
        const connectedUserResponse = await fetch('/users');
        let connectedUsers = await connectedUserResponse.json();
        connectedUsers = connectedUsers.filter(user => user.email !== email);
        const connectedUsersList = document.querySelector('#connectedUsers');
        connectedUsersList.innerHTML = '';
        connectedUsers.forEach(user => {
            appendUserElement(user, connectedUsersList);
            if (connectedUsers.indexOf(user) < connectedUsers.length-1){
                const separator = document.createElement('li');
                separator.classList.add('separator');
                connectedUsersList.appendChild(separator);
            }
        });
    }
    function appendUserElement(user, connectedUsersList) {
        const listItem = document.createElement('li');
        listItem.classList.add('user-item');
        listItem.id = user.email;
        const emailSpan = document.createElement('span');
        emailSpan.textContent = user.email;
        const receivedMessages = document.createElement('span');
        receivedMessages.textContent = '';
        receivedMessages.classList.add('nbr-msg','hidden');
        listItem.append(emailSpan);
        listItem.append(receivedMessages);
        connectedUsersList.appendChild(listItem);
    }
    async function fetchAdminEmail(){
        try{
            const repsonse = await fetch('/admin');
            const data = await repsonse.json();
            return data.email;
        } catch (error){
            console.error("error: ",error);
            return null;
        }
    }
    document.addEventListener('DOMContentLoaded',function (){
        connect(event);
    });

错误日志

Failed to handle GenericMessage [payload=byte[47], headers={simpMessageType=MESSAGE, conversionHint=method 'addUser' parameter -1, contentType=application/json, 
simpSessionId=xmuzd12r, simpDestination=/user/topic}] to org.springframework.messaging.support.ExecutorSubscribableChannel$SendTask@3ad5d640 in UserDestinationMessageHandler[DefaultUserDestinationResolver[prefix=/user/]]

问题疑点

怀疑是MongoDB配置问题,因为预期创建的集合并未生成。

内容的提问来源于stack exchange,提问作者Hubert Kiszka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 02:07:08