java WebSocketStompClient 不会连接到 SockJS 端点

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30413380/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-02 17:05:10  来源:igfitidea点击:

WebSocketStompClient won't connect to SockJS endpoint

javaspringspring-websocket

提问by stacktrace

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

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

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:

我可以使用浏览器客户端成功连接。尝试使用 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);

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.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] 

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

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

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:

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

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.

浏览器客户端可以再次连接,但是java客户端又回到了原来的错误状态。

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

我应该能够在两个客户端之间共享同一个端点,还是在这种情况下我需要配置两个单独的端点?

回答by stacktrace

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:

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

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

它只允许使用 java 和 javascript 客户端都可以连接的一个端点:

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

回答by Brian Clozel

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:

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

"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.

现在您无需为"/hello"端点复制配置。您宁愿直接使用 websocket 端点,或者更好的是,使用带有 websocket 传输的 Java SockJS 客户端。请参阅参考文档中的完整示例

回答by qyvlik

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

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