Akka http从指令返回异步响应(java)

Akka http从指令返回异步响应(java),java,akka,akka-http,Java,Akka,Akka Http,我想要一个基于参与者的服务,可以通过http访问。 我是akka的新手,但经过研究,我得出结论,使用akka http将是我最好的方法 我正在实现一个使用akka http的服务器,如下所示: class MyServer extends AllDirectives { private final Http http; private final Materializer materializer; private final Flow<HttpRequest, H

我想要一个基于参与者的服务,可以通过http访问。
我是akka的新手,但经过研究,我得出结论,使用akka http将是我最好的方法

我正在实现一个使用akka http的服务器,如下所示:

class MyServer extends AllDirectives {
    private final Http http;
    private final Materializer materializer;
    private final Flow<HttpRequest, HttpResponse, NotUsed> routes;

    private ServerBinding binding;

    MyServer(final ActorSystem system) {
        this.http = Http.get(system);
        this.materializer = ActorMaterializer.create(system);
        this.routes = this.createRoutes().flow(system, materializer);
    }

    CompletionStage<ServerBinding> start() {
        return this.http
                .bindAndHandle(this.routes, ConnectHttp.toHost("localhost", DEFAULT_PORT), this.materializer)
                .thenApplyAsync(serverBinding -> {
                    this.binding = serverBinding;
                    return serverBinding;
                });
    }

    CompletionStage<BoxedUnit> stop() {
        return this.binding.unbind();
    }

    private Route createRoutes() {
        // create routes 
    }
}
在处理请求时(例如,
handleTypeOneGetRequest
),我希望将消息传递给适当的参与者(例如,
TypeOne
),并返回一个异步响应,当参与者返回响应消息时,将执行该响应

我的问题是,在处理指令时,我不知道如何访问
RequestContext

我的问题是:

  • 如何获取指令中的
    RequestContext
  • 我这样做对吗?有更好的方法吗

    • 不太确定我是否正确回答了你的问题,但就我回答你的问题而言,你基本上希望让演员处理你的请求,然后返回结果。我通常使用Scala,所以请不要介意我在Java8代码中可能出现的语法错误;)

      我通常使用akka ask模式检索参与者发送的响应对象的未来,然后使用onSuccess指令从未来提取实际值。 由于actor响应在默认情况下是非类型化的,所以您需要检查它是否是您期望的,然后您可以使用该值完成您的请求。(您可能还需要强制转换对象,以便响应封送器工作)

      提问模式:

      onSuccess指令:

      编辑

      您应该看看extract*指令:

      具体摘录:

      我想这就是你需要的


      编辑(由OP编辑) 以下是该问题的完整解决方案,包括
      HttpContext
      ,使用
      Actor
      进行异步响应,以及如何使其在java中工作:

      pathPrefix("typeOne", () ->
          path(PathMatchers.segment(), segment ->
              get(() ->
                  extract(
                      context -> context,
                      context -> onSuccess(() -> 
                          FutureConverters.toJava(Patterns.ask(ACTOR_REF, MESSAGE, TIMEOUT)),
                          extraction -> complete(DO_SOMETHING_WITH(segment, context, extraction))
                      ).orElse(...)
                  )
              )
          )
      )
      

      谢谢,这部分回答了我的问题(如何返回异步响应并要求参与者处理请求)。另一部分是如何访问指令中的
      RequestContext
      ,也就是说,当将消息传递给参与者时,我希望该消息包含
      RequestContext
      中的信息(post/get数据、标题等),但我还没有找到获取该信息的方法,您不需要RequestContext。根据我的回答改编得很有趣。谢谢你!我会在接下来的几天里玩它,当我使用它的时候,我可能会有更多关于这个的问题。那我就把答案记为正确答案。再次感谢!感谢您的回答,这基本上是正确的,我只需要将这两个问题结合起来(使用和actor以及获取
      RequestContext
      ),还需要从scala
      Future
      转换为java
      CompletionStage
      。为了未来读者的利益,我编辑了您的答案并添加了完整的解决方案。再次感谢!
      Timeout timeout = new Timeout(Duration.create(5, "seconds"));    
      
      private Route createRoutes() {
          return pathPrefix("typeOne", () ->
                      path(PathMatchers.segment(), id ->
                          get(() -> 
                                  onSuccess(() -> Patterns.ask(actor, id, timeout),
                                            extraction -> if (extraction instanceof WhatEverYouExpect) complete(extraction)
                                           )
                              )
          ));
      }
      
      final Route route = extract(
        ctx -> ctx.getRequest().getUri().toString().length() // extract anything you need and pack into your object
        len -> //use your object
      );
      
      pathPrefix("typeOne", () ->
          path(PathMatchers.segment(), segment ->
              get(() ->
                  extract(
                      context -> context,
                      context -> onSuccess(() -> 
                          FutureConverters.toJava(Patterns.ask(ACTOR_REF, MESSAGE, TIMEOUT)),
                          extraction -> complete(DO_SOMETHING_WITH(segment, context, extraction))
                      ).orElse(...)
                  )
              )
          )
      )