WebSocketStompClient无法连接到SockJS端点

时间:2015-05-23 13:40:16

标签: java spring spring-websocket

我正在使用新的(从版本4.2开始)java STOMP客户端支持。我的出发点是入门指南(Using WebSocket to build an interactive web application)。

示例中提供了以下端点:

@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: The HTTP response from the server [HTTP/1.1 200 OK
] did not permit the HTTP upgrade to 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 个答案:

答案 0 :(得分:22)

以下配置有效:

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();
}

答案 1 :(得分:5)

the reference documentation中所述:启用SockJS时,会为您配置多个传输。首先,客户端发送"GET /info"请求以了解支持的传输,然后根据其功能发送请求:

"http://host:port/myApp/myEndpoint/{server-id}/{session-id}/{transport}"

现在,您不需要为"/hello"端点复制配置。您更愿意直接使用websocket端点,或者更好的是,将Java SockJS客户端与websocket传输一起使用。请参阅the complete example in the reference documentation

答案 2 :(得分:0)

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