无法使用 WebSocket 发送回复
Unable to send reply using WebSocket
我找了很多教程,我觉得一切都很好,但是客户端从来没有收到响应消息。连接正常,正在调用控制器上的方法,但客户端的订阅似乎被忽略了。
配置class:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.setApplicationDestinationPrefixes("/app");
registry.enableSimpleBroker("/topic");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
stompEndpointRegistry.addEndpoint("/unify")
.withSockJS();
}
}
控制器class:
@Controller
public class StatusController {
@MessageMapping("/status")
@SendTo("/topic/reply")
public String status(@Payload String test) {
return test;
}
}
测试class:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class WebSocketConnectionTest {
@Value(${local.server.port})
private String port;
@Test
public void testResponse() {
SockJsClient sockJsClient = new SockJsClient(createTransportClient());
WebSocketStompClient stompClient = new WebSocketStompClient(sockJsClient);
stompClient.setMessageConverter(new MappingJackson2MessageConverter());
boolean exceptionThrowed = false;
final CompletableFuture<String> completableFuture = new CompletableFuture<>();
try {
StompSession session = stompClient.connect("ws://localhost: " + port + "/unify", new StompSessionHandlerAdapter() {}).get(1, TimeUnit.SECONDS);
session.subscribe("/topic/reply", new StompFrameHandler() {
@Override
public Type getPayloadType(StompHeaders headers) {
return String.class;
}
@Override
public void handleFrame(StompHeaders headers, Object payload) {
completableFuture.complete((String)payload);
}
});
session.send("/app/status", "test");
// Always fails
String resp = completableFuture.get(5, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
e.printStackTrace(); // Always timeout exception
exceptionThrowed = true;
}
Assert.assertFalse(exceptionThrowed);
}
private List<Transport> createTransportClient() {
List<Transport> transports = new ArrayList<>(1);
transports.add(new WebSocketTransport(new StandardWebSocketClient()));
return transports;
}
}
我确信我遗漏了一些非常简单的东西,但我已经尝试了两天不同的配置但没有成功。
解决方案
看起来响应 class 需要有一个任何类型的字段 "content" 和一个对应的 getContent() (不知道 getContent() 是否真的有必要)。
我找了很多教程,我觉得一切都很好,但是客户端从来没有收到响应消息。连接正常,正在调用控制器上的方法,但客户端的订阅似乎被忽略了。
配置class:
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.setApplicationDestinationPrefixes("/app");
registry.enableSimpleBroker("/topic");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry stompEndpointRegistry) {
stompEndpointRegistry.addEndpoint("/unify")
.withSockJS();
}
}
控制器class:
@Controller
public class StatusController {
@MessageMapping("/status")
@SendTo("/topic/reply")
public String status(@Payload String test) {
return test;
}
}
测试class:
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class WebSocketConnectionTest {
@Value(${local.server.port})
private String port;
@Test
public void testResponse() {
SockJsClient sockJsClient = new SockJsClient(createTransportClient());
WebSocketStompClient stompClient = new WebSocketStompClient(sockJsClient);
stompClient.setMessageConverter(new MappingJackson2MessageConverter());
boolean exceptionThrowed = false;
final CompletableFuture<String> completableFuture = new CompletableFuture<>();
try {
StompSession session = stompClient.connect("ws://localhost: " + port + "/unify", new StompSessionHandlerAdapter() {}).get(1, TimeUnit.SECONDS);
session.subscribe("/topic/reply", new StompFrameHandler() {
@Override
public Type getPayloadType(StompHeaders headers) {
return String.class;
}
@Override
public void handleFrame(StompHeaders headers, Object payload) {
completableFuture.complete((String)payload);
}
});
session.send("/app/status", "test");
// Always fails
String resp = completableFuture.get(5, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
e.printStackTrace(); // Always timeout exception
exceptionThrowed = true;
}
Assert.assertFalse(exceptionThrowed);
}
private List<Transport> createTransportClient() {
List<Transport> transports = new ArrayList<>(1);
transports.add(new WebSocketTransport(new StandardWebSocketClient()));
return transports;
}
}
我确信我遗漏了一些非常简单的东西,但我已经尝试了两天不同的配置但没有成功。
解决方案
看起来响应 class 需要有一个任何类型的字段 "content" 和一个对应的 getContent() (不知道 getContent() 是否真的有必要)。