为了账号安全,请及时绑定邮箱和手机立即绑定

如何异步接受 WebSocket?

如何异步接受 WebSocket?

皈依舞 2023-06-14 16:30:27
我有一个处理 WebSocket 请求的 Play 应用程序。路由文件包含这一行:GET  /testsocket  controllers.HomeController.defaultRoomSocket一个已经工作的同步版本如下所示:(改编自 2.7.x 文档)public WebSocket defaultRoomSocket() {    return WebSocket.Text.accept(        request -> ActorFlow.actorRef(MyWebSocketActor::props, actorSystem, materializer));  }如https://www.playframework.com/documentation/2.7.x/JavaWebSockets#Accepting-a-WebSocket-asynchronously所述,我将签名更改为public CompletionStage<WebSocket> defaultRoomSocket(){   //returning a CompletionStage here, using the "ask pattern"   //to get the needed Flow from an other Actor}从这里我遇到了以下问题:Cannot use a method returning java.util.concurrent.CompletionStage[play.mvc.WebSocket] as a Handler for requests此外,正如文档所建议的那样,“WebSocket”没有类型参数。接受 WebSocket 请求异步的合适方法是什么?
查看完整描述

1 回答

?
翻翻过去那场雪

TA贡献2065条经验 获得超13个赞

文档确实需要更新,我认为在#5055 的websockets 重构中遗漏了一些位。

要获得异步处理,您应该使用acceptOrResult以 aCompletionStage作为返回类型而不是流的方法。然后可以使用函数式编程助手 ( ) 返回 aResult或 Akka 。事实上,下面是该方法的实现方式:FlowF.Eitheraccept

public WebSocket accept(Function<Http.RequestHeader, Flow<In, Out, ?>> f) { 
  return acceptOrResult(
       request -> CompletableFuture.completedFuture(F.Either.Right(f.apply(request))));
}

如您所见,它所做的只是调用带有completedFuture.

为了完全使其异步并达到我认为你想要实现的目标,你会做这样的事情:

public WebSocket ws() {

    return WebSocket.Json.acceptOrResult(request -> {

        if (sameOriginCheck(request)) {

            final CompletionStage<Flow<JsonNode, JsonNode, NotUsed>> future = wsFutureFlow(request);

            final CompletionStage<Either<Result, Flow<JsonNode, JsonNode, ?>>> stage = future.thenApply(Either::Right);

            return stage.exceptionally(this::logException);

        } else {

            return forbiddenResult();

        }

    });

}


@SuppressWarnings("unchecked")

private CompletionStage<Flow<JsonNode, JsonNode, NotUsed>> wsFutureFlow(Http.RequestHeader request) {

    long id = request.asScala().id();

    UserParentActor.Create create = new UserParentActor.Create(Long.toString(id));


    return ask(userParentActor, create, t).thenApply((Object flow) -> {

        final Flow<JsonNode, JsonNode, NotUsed> f = (Flow<JsonNode, JsonNode, NotUsed>) flow;

        return f.named("websocket");

    });

}


private CompletionStage<Either<Result, Flow<JsonNode, JsonNode, ?>>> forbiddenResult() {

    final Result forbidden = Results.forbidden("forbidden");

    final Either<Result, Flow<JsonNode, JsonNode, ?>> left = Either.Left(forbidden);


    return CompletableFuture.completedFuture(left);

}


private Either<Result, Flow<JsonNode, JsonNode, ?>> logException(Throwable throwable) {

    logger.error("Cannot create websocket", throwable);

    Result result = Results.internalServerError("error");

    return Either.Left(result);

}

(这取自play-java-websocket-example,这可能很有趣)

如您所见,它首先经过几个阶段,然后返回 websocket 连接或 HTTP 状态。


查看完整回答
反对 回复 2023-06-14
  • 1 回答
  • 0 关注
  • 132 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信