WebSocketStompClient无法连接到SockJS端点

14

我正在尝试使用新的(从4.2版本开始)Java STOMP客户端支持。我的起点是入门指南(使用WebSocket构建交互式Web应用程序)。

示例中提供了以下端点:

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

我可以成功使用浏览器客户端进行连接。当尝试使用以下Java STOMP客户端连接到此端点时:

WebSocketClient transport = new StandardWebSocketClient();
WebSocketStompClient stompClient = new WebSocketStompClient(transport);
stompClient.setMessageConverter(new StringMessageConverter());
String url = "ws://127.0.0.1:8080/hello";       
ListenableFuture<StompSession> future = stompClient.connect(url,myHandler);

我遇到了以下异常:

08:56:30.629 [SimpleAsyncTaskExecutor-1] DEBUG o.s.m.simp.stomp.DefaultStompSession - Failed to connect session id=4e6737da-8f68-691d-375f-9e46f48bc149
javax.websocket.DeploymentException:服务器的HTTP响应[HTTP / 1.1 200 OK]不允许将HTTP升级为WebSocket
    at org.apache.tomcat.websocket.WsWebSocketContainer.parseStatus(WsWebSocketContainer.java:637) ~[tomcat-embed-websocket-8.0.20.jar:8.0.20]
    at org.apache.tomcat.websocket.WsWebSocketContainer.processResponse(WsWebSocketContainer.java:621) ~[tomcat-embed-websocket-8.0.20.jar:8.0.20]
    at org.apache.tomcat.websocket.WsWebSocketContainer.connectToServer(WsWebSocketContainer.java:309) ~[tomcat-embed-websocket-8.0.20.jar:8.0.20]
    at org.springframework.web.socket.client.standard.StandardWebSocketClient$1.call(StandardWebSocketClient.java:152) ~[spring-websocket-4.2.0.BUILD-SNAPSHOT.jar:4.2.0.BUILD-SNAPSHOT]
    at org.springframework.web.socket.client.standard.StandardWebSocketClient$1.call(StandardWebSocketClient.java:149) ~[spring-websocket-4.2.0.BUILD-SNAPSHOT.jar:4.2.0.BUILD-SNAPSHOT]
    at java.util.concurrent.FutureTask.run(Unknown Source) [na:1.8.0]
    at java.lang.Thread.run(Unknown Source) [na:1.8.0]

经过进一步调查,我根据StompWebSocketIntegrationTests.java中使用的TomcatWebSocketTestServer.java更改了服务器端点配置如下:

RequestUpgradeStrategy upgradeStrategy = new TomcatRequestUpgradeStrategy();
registry.addEndpoint("/hello")
    .setHandshakeHandler(new DefaultHandshakeHandler(upgradeStrategy))
    .setAllowedOrigins("*");

我现在可以连接,但浏览器客户端不能连接。

GET http://localhost:8080/hello/info 404 (Not Found) 

如果我将.withSockJs()添加到端点配置中:

RequestUpgradeStrategy upgradeStrategy = new TomcatRequestUpgradeStrategy();
registry.addEndpoint("/hello")
    .setHandshakeHandler(new DefaultHandshakeHandler(upgradeStrategy))
    .setAllowedOrigins("*")
    .withSockJs();
浏览器客户端可以重新连接,但Java客户端回到原始错误。
在这种情况下,我应该能够在两个客户端之间共享相同的终端点吗?还是我需要配置两个单独的终端点?
3个回答

26
以下配置可以正常工作:
RequestUpgradeStrategy upgradeStrategy = new TomcatRequestUpgradeStrategy();
registry.addEndpoint("/hello")
        .withSockJS();

registry.addEndpoint("/hello")
        .setHandshakeHandler(new DefaultHandshakeHandler(upgradeStrategy))
        .setAllowedOrigins("*");

不确定这是否是设计上的问题(即具有相同路径的两个端点)?

根据Brian-Clozel的反馈,更好的解决方案是在配置WebSocketStompClient时使用java SockJsClient作为传输。

List<Transport> transports = new ArrayList<>(1);
transports.add(new WebSocketTransport( new StandardWebSocketClient()) );
WebSocketClient transport = new SockJsClient(transports);
WebSocketStompClient stompClient = new WebSocketStompClient(transport);

这使得Java和JavaScript客户端都可以连接到同一个终节点进行使用:

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

我认为你可以把它写成一个,不是吗?registry.addEndpoint("/hello").setHandshakeHandler(new DefaultHandshakeHandler(upgradeStrategy)).setAllowedOriginPatterns("*").withSockJS();另外,将 setAllowedOrigins 更改为 setAllowedOriginPatterns - Daniel Gannota

6
参考文档所述:启用SockJS时,会为您配置多个传输。首先,客户端发送"GET /info"请求以了解支持的传输方式,然后根据其能力发送请求。
"http://host:port/myApp/myEndpoint/{server-id}/{session-id}/{transport}"

现在,您不需要为您的"/hello"端点复制配置。相反,您可以直接使用websocket端点,或者更好地,使用具有websocket传输的Java SockJS客户端。请参见参考文档中的完整示例

谢谢,你的回答很有帮助。根据你的反馈,我已经更新了我的回答配置。抱歉我还不能点赞(声望值不够)。 - stacktrace

0

您可以检查http过滤器(例如shiro过滤器)或HandlerInterceptor。

WebSocket连接基于http连接,有一个类似于ws://localhost:8080/ws-endpoint的ws url。如果在uri ws-endpoint上有http过滤器或http拦截器,则在websocket升级之前将影响http过滤器或http拦截器。因此,请删除uri的http过滤器或http拦截器。


请更详细地解释一下。 - Jan Černý
WebSocket连接基于HTTP连接,有一个类似于ws://localhost:8080/ws-endpoint的ws URL。如果您在uri ws-endpoint上有一个http过滤器或http拦截器,则在WebSocket升级之前将影响http过滤器或http拦截器。因此,请删除URI的http过滤器或http拦截器。@jan-Černý - qyvlik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接