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

Spring Boot MVC与Security环境下能否将Spring WebSocket的STOMP客户端JS代码迁移至服务端?

Spring WebSocket STOMP Client Logic: Can It Move to the Server?

Hey there! Let's unpack your questions about Spring WebSocket, STOMP, and that client-side JavaScript code you're looking to migrate. I'll break this down clearly so you understand the "why" behind the current setup and what you can (and can't) adjust.

1. Can You Move STOMP Client JavaScript to the Server?

Short answer: No, you can't fully migrate that client-side logic to the server—and it all comes down to how WebSocket (and STOMP) works. Let me explain:

  • WebSocket is a bidirectional, client-server communication protocol. For your chat app, the browser (client) needs to initiate a WebSocket connection to your Spring Boot server. The new SockJS('/hello') call is the browser's way of starting that connection handshake—something the server can't do on behalf of the browser.
  • STOMP is a messaging protocol that runs on top of WebSocket. The client-side stompClient instance is the browser's "messaging client" that subscribes to topics, sends messages, and receives updates. The server acts as the STOMP broker/handler, but it can't replace the client's role in maintaining that connection and interacting with the user's browser.
  • DOM operations (like the showGreeting function that builds chat message elements) can only happen in the browser. The server has no access to the user's DOM, so it can't create or append HTML elements to their page.

2. Why Do You Need to Reconnect on Page Refresh?

When you refresh the page, the browser resets its entire JavaScript context: your old stompClient instance is destroyed, and the WebSocket connection is closed. That's why you need window.onload = connect()—it reinitializes the connection when the new page loads.

Good news though: your JSESSIONID cookie persists across page refreshes, so when you reconnect, the server can still identify the logged-in user (thanks to Spring Security). You don't have to re-authenticate the user for the WebSocket connection.

3. What Can You Do Instead of Migrating?

While you can't move the client-side logic to the server, you can optimize it to be cleaner and more robust:

  • Extract the JS to a separate file: Instead of embedding it in your HTML, move the code to a chat.js file. This makes it easier to maintain and reuse.
  • Add reconnection logic: If the WebSocket drops (e.g., network blip), add a retry mechanism to automatically reconnect instead of making the user click a button.
  • Let the server handle data, not HTML: Instead of trying to generate HTML on the server, send raw message data (username, content, timestamp, avatar URL) from the server. The client's showGreeting function can then render that data into HTML—this keeps concerns separated (server manages data, client manages presentation).
  • Secure the WebSocket connection: You're already using JSESSIONID, but make sure your Spring Security config restricts WebSocket access to authenticated users.

Your Original Client-Side Code (For Reference)

var stompClient = null;

window.onload = function () {
    connect();
}

function setConnected(connected) {
    document.getElementById('connect').disabled = connected;
    document.getElementById('disconnect').disabled = !connected;
    document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden';
    document.getElementById('response').innerHTML = '';
}

function connect() {
    const socket = new SockJS('/hello');
    stompClient = Stomp.over(socket);
    stompClient.connect({}, function(frame) {
        setConnected(true);
        console.log('Connected: ' + frame);
        stompClient.subscribe('/topic/greetings', function (outmessage) {
            const content = JSON.parse(outmessage.body).messageEntity.content;
            const time = JSON.parse(outmessage.body).messageEntity.date_create;
            const date = JSON.parse(outmessage.body).messageEntity.date;
            const user_name = JSON.parse(outmessage.body).userEntity.user_name;
            const user_avat = JSON.parse(outmessage.body).userEntity.user_avatar;
            showGreeting(content, user_name, time, date, user_avat);
        });
    });
}

function disconnect() {
    stompClient.disconnect();
    setConnected(false);
    console.log("Disconnected");
}

function sendMessage() {
    const message = document.getElementById('text').value;
    stompClient.send("/app/hello", {}, JSON.stringify({ 'text': message }));
}

function showGreeting (message, user_name, date_time, date, avatar) {
    const ul = document.getElementById('ul-message');
    const li = document.createElement('li');
    const p_mes = document.createElement('p');
    const p_user = document.createElement('p');
    const p_time = document.createElement('p');
    const div_container = document.createElement('div');
    const img_chat_ava = document.createElement('img');
    const div_chat_name = document.createElement('div');
    const div_chat_mess = document.createElement('div');
    const div_chat_time = document.createElement('div');

    img_chat_ava.src = avatar;
    div_container.classList.add("message-container");
    div_chat_mess.classList.add("message");
    div_chat_time.classList.add("message-time");
    div_chat_name.classList.add("chat-name");
    img_chat_ava.classList.add("avatar");

    li.appendChild(div_container);
    div_container.appendChild(img_chat_ava);
    div_container.appendChild(div_chat_name);
    div_container.appendChild(div_chat_mess);
    div_container.appendChild(div_chat_time);

    p_mes.style.wordWrap = 'break-word';
    p_mes.appendChild(document.createTextNode(message));
    p_user.appendChild(document.createTextNode(user_name));
    p_time.appendChild(document.createTextNode(date_time + " " + date));

    div_chat_mess.appendChild(p_mes);
    div_chat_name.appendChild(p_user);
    div_chat_time.appendChild(p_time);
    ul.appendChild(li);
}

内容的提问来源于stack exchange,提问作者Pawsy Foxicute

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 05:37:50