WebSocketStompClient 不会连接到 SockJS 端点
WebSocketStompClient won't connect to SockJS endpoint
我正在尝试新的(从 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.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.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客户端又回到原来的错误。
我应该能够在两个客户端之间共享同一个端点,还是在这种情况下我需要配置两个单独的端点?
以下配置有效:
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 和 java 脚本客户端都可以连接的一个端点:
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/hello").withSockJS();
}
如 the reference documentation 所述:启用 SockJS 时,会为您配置多个传输。首先,客户端发送一个 "GET /info"
请求以了解支持的传输,然后根据其能力发送一个请求:
"http://host:port/myApp/myEndpoint/{server-id}/{session-id}/{transport}"
现在您不需要为 "/hello"
端点复制配置。您宁愿直接使用 websocket 端点,或者更好地使用带有 websocket 传输的 Java SockJS 客户端。参见 the complete example in the reference documentation。
你可以勾选http过滤器(比如shiro过滤器)或者HandlerInterceptor。
WebSocket connnect based on http connect, ws url 是这样的: ws://localhost:8080/ws-endpoint, 如果你在uri ws-上有http过滤器或者http拦截器端点、http 过滤器或 http 拦截器将在 websocket 升级之前生效。所以去掉uri的http过滤器或者http拦截器。
我正在尝试新的(从 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.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.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客户端又回到原来的错误。
我应该能够在两个客户端之间共享同一个端点,还是在这种情况下我需要配置两个单独的端点?
以下配置有效:
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 和 java 脚本客户端都可以连接的一个端点:
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/hello").withSockJS();
}
如 the reference documentation 所述:启用 SockJS 时,会为您配置多个传输。首先,客户端发送一个 "GET /info"
请求以了解支持的传输,然后根据其能力发送一个请求:
"http://host:port/myApp/myEndpoint/{server-id}/{session-id}/{transport}"
现在您不需要为 "/hello"
端点复制配置。您宁愿直接使用 websocket 端点,或者更好地使用带有 websocket 传输的 Java SockJS 客户端。参见 the complete example in the reference documentation。
你可以勾选http过滤器(比如shiro过滤器)或者HandlerInterceptor。
WebSocket connnect based on http connect, ws url 是这样的: ws://localhost:8080/ws-endpoint, 如果你在uri ws-上有http过滤器或者http拦截器端点、http 过滤器或 http 拦截器将在 websocket 升级之前生效。所以去掉uri的http过滤器或者http拦截器。