Spring Boot WebSocket-将主体添加到CONNECT响应

时间:2018-12-26 02:04:54

标签: 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;
}

我目前正在做的以***开头的注释行没有成功。我究竟做错了什么?我什至可以这样做并向客户端获取一些参数?如果我做错了,怎么做以及在哪里做对? (因为现在我开始觉得自己正在尝试在错误的位置进行操作)

1 个答案:

答案 0 :(得分:0)

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

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,它将添加一些自定义标头(是的,我最初试图添加主体,但是出于测试目的,我坚持了暂时显示在标题中。

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

然后,我再次引用STOMP Protocol Spec(感谢@TimBish在上面的评论)并从那里阅读此声明。

  

只有SEND,MESSAGE和ERROR帧可以带有主体。其他所有框架都不得有车身。

因此,似乎我们无法截获SENDMESSAGEERROR以外的消息。我认为这是因为遵守Spring的STOMP实现的协议规范。

为什么我尝试这样做是为了在每个连接的客户端和服务器之间共享一些公共机密,而该机密由服务器确定。仍在寻找这种实现方式。