두 Java 환경 간의 통신을 구현해야합니다. 수신자는 SpringBoot 리 액티브 애플리케이션이고 통신을 처리하기위한 스 니펫은 다음과 같습니다 (빈 구성은 건너 뛰겠습니다).
@Override
public Mono<Void> handle(WebSocketSession webSocketSession) {
return webSocketSession.send(webSocketSession.receive() // <- Step 0
.map(message -> {
log.info("Step 1");
return message.getPayloadAsText();
})
.map(message -> {
log.info("Step 2");
return webSocketSession.textMessage(this.receiveMessage(message));
}));
}
클라이언트 부분은 Java 11의 Http API를 사용하여 구현됩니다.
WebSocket webSocket = HttpClient
.newBuilder().executor(executor).build()
.newWebSocketBuilder()
.buildAsync(URI.create(url), new WebSocket.Listener() {
@Override
public void onOpen(WebSocket webSocket) {
log.info("onOpen using subprotocol " + webSocket.getSubprotocol());
WebSocket.Listener.super.onOpen(webSocket);
}
@Override
public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) {
log.info("onText received with data " + data);
return WebSocket.Listener.super.onText(webSocket, data, last);
}
@Override
public CompletionStage<?> onClose(WebSocket webSocket, int statusCode, String reason) {
log.info("Closed with status " + statusCode + ", reason: " + reason);
return WebSocket.Listener.super.onClose(webSocket, statusCode, reason);
}
@Override
public void onError(WebSocket webSocket, Throwable error) {
log.error("Error: " + error.getMessage());
WebSocket.Listener.super.onError(webSocket, error);
}
}).join();
webSocket.sendText(toJSON(List.of("Lorem", "Ipsum", "dolor", "sit", "amet")), true);
webSocket.sendClose(WebSocket.NORMAL_CLOSURE, "ok").thenRun(() -> log.info("Sent close"));
디버그를 사용하면 join()
이 완료되고 WebSocket
인스턴스가 반환되면 수신자의 Step 0에서 메서드가 실행되고 Mono<Void>
인스턴스가 반환 됨을 알 수 있습니다 .
하지만 문제는 내가 문자를 보내도 1 단계와 2 단계가 실행되지 않는다는 것입니다!
역방향 통신을 시도하면 (SpringBoot 애플리케이션에서 Sender 앱으로 무언가 전송) 메시지가 수신됩니다.
마지막으로 이것은 명령문 onClose
이후의 콜백 실행 로그입니다 sendClose
.
Closed with status 1002, reason: Server internal error
해결책
buildAsync
메서드가의 인스턴스를 반환 하므로 다음을 CompletableFuture<WebSocket>
사용하여 메시지 대기열을 플러시하기 전에 메시지 전송 체인이 필요합니다.join()
여기에 해결책
WebSocket webSocket = HttpClient
.newBuilder().executor(executor).build()
.newWebSocketBuilder()
.buildAsync(URI.create(url), new WebSocket.Listener() {
@Override
public void onOpen(WebSocket webSocket) {
log.info("onOpen using subprotocol " + webSocket.getSubprotocol());
WebSocket.Listener.super.onOpen(webSocket);
}
@Override
public CompletionStage<?> onText(WebSocket webSocket, CharSequence data, boolean last) {
log.info("onText received with data " + data);
return WebSocket.Listener.super.onText(webSocket, data, last);
}
@Override
public CompletionStage<?> onClose(WebSocket webSocket, int statusCode, String reason) {
log.info("Closed with status " + statusCode + ", reason: " + reason);
return WebSocket.Listener.super.onClose(webSocket, statusCode, reason);
}
@Override
public void onError(WebSocket webSocket, Throwable error) {
log.error("Error: " + error.getMessage());
WebSocket.Listener.super.onError(webSocket, error);
}
})
.thenCompose(ws -> ws.sendText(toJSON(List.of("Lorem", "Ipsum", "dolor", "sit", "amet")), false))
.thenCompose(ws -> ws.sendText(toJSON(List.of("Lorem", "Ipsum", "dolor", "sit", "amet")), true))
.thenCompose(ws -> webSocket.sendClose(WebSocket.NORMAL_CLOSURE, ""))
.join();
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다