问题
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