java - Spring Boot WebSocket - 将正文添加到 CONNECT 响应

标签 java spring-boot websocket stomp

我有以下 JS 函数,它们通过 STOMP 连接到 WebSocket,并分别处理 onConnected 事件。

function connect(event) {
    username = document.querySelector('#name').value.trim();

    if(username) {
        usernamePage.classList.add('hidden');
        chatPage.classList.remove('hidden');

        var socket = new SockJS('/ws');
        stompClient = Stomp.over(socket);

        stompClient.connect({}, onConnected, onError);
    }
    event.preventDefault();
}


function onConnected(response) {
    console.log(response);
    // Subscribe to the Public Topic
    stompClient.subscribe('/topic/public', onMessageReceived);

    // Tell your username to the server
    stompClient.send("/app/chat.addUser",
        {},
        JSON.stringify({sender: username, type: 'JOIN'})
    )

    connectingElement.classList.add('hidden');
}

现在函数 onConnected 的第一行,它将以下内容记录到控制台中,这显然看起来像是我可以从服务器端添加更多数据的东西。

{
    command: "CONNECTED",
    headers: { 
        "heart-beat": "0,0",
        version: "1.1"
    },
    body: ""
}

我还有一个HttpHandshakeInterceptor,它实现了HandshakeInterceptor,如下所示。

@Override
public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
        Map attributes) throws Exception {
    if (request instanceof ServletServerHttpRequest) {
        ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
        HttpSession session = servletRequest.getServletRequest().getSession();
        attributes.put("sessionId", session.getId());

        ServletServerHttpResponse servletResponse = (ServletServerHttpResponse) response;
        response.getHeaders().set("KEY","VALUE"); // *** I want this either to be in the response header or the body.
    }
    return true;
}

*** 开头的注释行是我现在正在做的事情,但没有成功。我究竟做错了什么?我什至可以这样做并向客户端获取一些参数吗?如果我做错了,如何以及在哪里做正确? (因为现在我开始觉得我在错误的地方尝试这样做)

最佳答案

好的。因此,以下是我尝试做的事情,没有成功

public class OutboundMessageInterceptor implements ChannelInterceptor {

    private static final Logger LOGGER = LoggerFactory.getLogger(OutboundMessageInterceptor.class);

    @Override
    public Message<?> preSend(Message<?> message, MessageChannel channel) {
        final StompHeaderAccessor headerAccessor = StompHeaderAccessor.wrap(message);
        final StompCommand command = headerAccessor.getCommand();

        LOGGER.info("Outbound channel preSend (" + command + ")...");

        if (command != null) {

            switch (command) {

                case CONNECTED:
                    final StompHeaderAccessor accessor = StompHeaderAccessor.create(headerAccessor.getCommand());
                    accessor.setSessionId(headerAccessor.getSessionId());
                    @SuppressWarnings("unchecked")
                    final MultiValueMap<String, String> nativeHeaders = (MultiValueMap<String, String>) headerAccessor.getHeader(StompHeaderAccessor.NATIVE_HEADERS);
                    accessor.addNativeHeaders(nativeHeaders);

                    // add custom headers
                    accessor.addNativeHeader("CUSTOM01", "CUSTOM01");

                    return MessageBuilder.createMessage(new byte[0], accessor.getMessageHeaders());
                default:
                    break;
            }
        }

        return message;
    }
}

这基本上做的是,拦截服务器中的出站消息,如果消息是CONNECTED,它将添加一些自定义 header (是的,我最初尝试添加正文,但为了测试目的我暂时坚持标题)。

但是,此方法可以拦截许多 STOMP 命令,CONNECTED 除外。我没有试图拦截其他人,但可能应该这样做。

然后我又引用了STOMP Protocol Spec (感谢@TimBish 的上述评论)并从那里阅读此声明。

Only the SEND, MESSAGE, and ERROR frames MAY have a body. All other frames MUST NOT have a body.

因此,除了 SENDMESSAGEERROR 之外,我们似乎无法拦截其他消息。我认为这是因为遵守 Spring STOMP 实现的协议(protocol)规范。

我尝试这样做的原因是为了在每个连接的客户端和服务器之间共享一些公共(public) secret ,其中 secret 由服务器确定。仍在寻找这样的实现。

关于java - Spring Boot WebSocket - 将正文添加到 CONNECT 响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53926802/

相关文章:

java.io.FileNotFoundException : (No such file or directory) - Working with servlets 错误

java - 对自定义对象的 vector 进行排序

java - 由于递归而导致无限循环(介绍性)

mysql - spring boot报错突然没有网络连接

python - Telegram 的 websocket

java - 如何设置ViewingPlatform和更新TransformGroup?

spring-boot - 由于缺少 around 注释,Spring Boot 测试无法加载 ApplicationContext

java - 用于自定义 Servlet 的 Spring Boot Actuator

php - 如何在 XAMPP 服务器中使用 WebSocket

javascript - 我如何创建自己的 url,如 ws ://echo. websocket.org?