WebSocketStompClient won't connect to SockJS endpoint

梦想与她 提交于 2019-12-20 12:20:52

问题


I'm playing around with the new (as of version 4.2) java STOMP client support. My starting point is the getting started guide (Using WebSocket to build an interactive web application).

The following endpoint is provided in the example:

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

I can successfully connect using the browser client. When attempting to connect to this endpoint using the java stomp client using the following:

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

I encounter the following exception:

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] 

Upon further investigation I changed the server endpoint configuration based on TomcatWebSocketTestServer.java used in StompWebSocketIntegrationTests.java as follows:

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

I can now connect, but the browser clients cannot.

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

If I add .withSockJs() to the endpoint configuration:

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

the browser clients can connect again, but the java client is back to the original error.

Should I be able to share the same endpoint between both clients or do I need to configure two separate endpoints in this case?


回答1:


The following configuration works:

RequestUpgradeStrategy upgradeStrategy = new TomcatRequestUpgradeStrategy();
registry.addEndpoint("/hello")
        .withSockJS();

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

Not sure if this is by design (i.e. two endpoints with the same path)?

A better solution based on Brian-Clozel's feedback is to use the java SockJsClient as a transport when configuring the WebSocketStompClient:

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

which allows the use of only one endpoint to which the java and javascript clients can both connect:

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



回答2:


As stated in the reference documentation: when enabling SockJS, multiple transports are configured for you. First, the client sends a "GET /info" request to know about supported transports and then sends a request depending on its capabilities:

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

Now you don't need to duplicate your configuration for you "/hello" endpoint. You'd rather directly use the websocket endpoint, or better, use the Java SockJS client with a websocket transport. See the complete example in the reference documentation.




回答3:


You can check the http filter(such as shiro filter) or HandlerInterceptor.



来源:https://stackoverflow.com/questions/30413380/websocketstompclient-wont-connect-to-sockjs-endpoint

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!