HttpApp 引导程序

HttpApp Bootstrap

API may change

This is experimental and the API is subjected to change in future releases of Akka HTTP. For further information about this marker, see The @DoNotInherit and @ApiMayChange markers in the Akka documentation.

这是实验性的并且在未来的 Akka HTTP 发布里随时变化。有关该标记的进一步信息,见 Akka 文档里的 @DoNotInherit 和 @ApiMayChange 标记

Introduction

导读

The objective of HttpAppHttpApp is to help you start an HTTP server with just a few lines of code. This is accomplished just by extending HttpAppHttpApp and implementing the routes() method. If desired, HttpAppHttpApp provides different hook methods that can be overridden to change its default behavior.

HttpAppHttpApp 的目的是帮助你仅用几行代码行来启动一个 HTTP 服务器。通过扩展 HttpAppHttpApp 并实例 routes 方法来完成。 如有需要, HttpAppHttpApp 提供了不同的挂勾方法,可以将其重写以改变默认行为。

Please note that HttpAppHttpApp is not the canonical way of starting an akka-http server. It is a tool to get up and running fast. For integrating into already existing Akka applications that already bring their ActorSystemActorSystem using Http.bindAndHandle (which is also just a single line of code) is recommended over using HttpAppHttpApp.

请注意, HttpAppHttpApp 不是启动 akka-http 服务器的权威方法。它是一种快速启动并运行的工具。 为了集成到已经提供了 ActorSystemActorSystem 的现有 Akka 应用程序中,建议使用 Http.bindAndHandle (它也只有一行代码),而不使用 HttpAppHttpApp

Minimal Example

小的示例

The following example shows how to start a server:

下面例子显示怎样启动一个服务器:

Scala
import akka.http.scaladsl.model.{ ContentTypes, HttpEntity }
import akka.http.scaladsl.server.HttpApp
import akka.http.scaladsl.server.Route

// Server definition
object WebServer extends HttpApp {
  override def routes: Route =
    path("hello") {
      get {
        complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, "<h1>Say hello to akka-http</h1>"))
      }
    }
}

// Starting the server
WebServer.startServer("localhost", 8080)
Java
import akka.Done;
import akka.actor.ActorSystem;
import akka.http.javadsl.server.HttpApp;
import akka.http.javadsl.server.Route;
import java.util.Optional;
import java.util.concurrent.*;

// Server definition
class MinimalHttpApp extends HttpApp {
  @Override
  protected Route routes() {
    return path("hello", () ->
      get(() ->
        complete("<h1>Say hello to akka-http</h1>")
      )
    );
  }
}

// Starting the server
final MinimalHttpApp myServer = new MinimalHttpApp();
myServer.startServer("localhost", 8080);

Firstly we define an object (it can also be a class)a class that extends HttpAppHttpApp and we just implement the routes this server will handle. After that, we can start a server just by providing a host and a port. Calling startServer blocks the current thread until the server is signaled for termination. The default behavior of HttpAppHttpApp is to start a server, and shut it down after ENTER is pressed. When the call to startServer returns the server is properly shut down.

首先,我们定义 一个 object (也可以使用 class)一个 class 扩展 HttpAppHttpApp 并实现这个服务器将处理的路由。 然后,我们通过提供 hostport 启动服务器。调用 startServer 阻塞当前线程直接服务器发出终止信息。 HttpAppHttpApp 的默认行为是启动一个服务器,然后按 ENTER 后将其关闭。当对 startServer 的调用返回时,服务器已正确关闭。

Reacting to Bind Failures

应对绑定失败

HttpAppHttpApp provides different hooks that will be called after a successful and unsuccessful initialization. For example, the server might not start due to the port being already in use, or because it is a privileged one.

当初始化成功或失败后, HttpAppHttpApp 提供了不同的挂勾被调用。例如:由于端口已被占用导致服务器无法启动或者该端口是一个特权端口。

Here you can see an example server that overrides the postHttpBindingFailure hook and prints the error to the console (this is also the default behavior)

这里你可以看到一个示例服务器,重写了 postHttpBindingFailure 钩子并打印错误到控制台(这也是默认行为)。

Scala
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.http.scaladsl.server.HttpApp
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.settings.ServerSettings
import com.typesafe.config.ConfigFactory

// Server definition
object WebServer extends HttpApp {
  override def routes: Route =
    path("hello") {
      get {
        complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, "<h1>Say hello to akka-http</h1>"))
      }
    }

  override protected def postHttpBinding(binding: Http.ServerBinding): Unit = {
    super.postHttpBinding(binding)
    val sys = systemReference.get()
    sys.log.info(s"Running on [${sys.name}] actor system")
  }

  override protected def postHttpBindingFailure(cause: Throwable): Unit = {
    println(s"The server could not be started due to $cause")
  }
}

// Starting the server
WebServer.startServer("localhost", 80, ServerSettings(ConfigFactory.load))
Java
import akka.Done;
import akka.actor.ActorSystem;
import akka.http.javadsl.server.HttpApp;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.settings.ServerSettings;
import akka.http.javadsl.ServerBinding;
import com.typesafe.config.ConfigFactory;
import java.util.Optional;
import java.util.concurrent.*;

// Server definition
class FailBindingOverrideHttpApp extends HttpApp {

  @Override
  protected Route routes() {
    return path("hello", () ->
      get(() ->
        complete("<h1>Say hello to akka-http</h1>")
      )
    );
  }

  @Override
  protected void postHttpBinding(ServerBinding binding) {
    super.postHttpBinding(binding);
    final ActorSystem sys = systemReference.get();
    sys.log().info("Running on [" + sys.name() + "] actor system");
  }

  @Override
  protected void postHttpBindingFailure(Throwable cause) {
    System.out.println("I can't bind!");
  }
}

// Starting the server
final FailBindingOverrideHttpApp myServer = new FailBindingOverrideHttpApp();
myServer.startServer("localhost", 80, ServerSettings.create(ConfigFactory.load()));

So if the port 80 would be already taken by another app, the call to startServer returns immediately and the postHttpBindingFailure hook will be called.

如果端口 80 已经被其它应用占用,调用 startServer 立即返回并且 postHttpBindingFailure 钩子将被调用。

Providing your own Server Settings

提供你自己的服务器设置

HttpAppHttpApp reads the default ServerSettingsServerSettings when one is not provided. In case you want to provide different settings, you can simply pass it to startServer as illustrated in the following example:

当没有提供 ServerSettingsServerSettings 时, HttpAppHttpApp 读取默认设置。你希望提供不同的设置,可以如例所示简单传递配置到 startServer

Scala
import akka.http.scaladsl.model.{ ContentTypes, HttpEntity }
import akka.http.scaladsl.server.HttpApp
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.settings.ServerSettings
import com.typesafe.config.ConfigFactory

// Server definition
object WebServer extends HttpApp {
  override def routes: Route =
    path("hello") {
      get {
        complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, "<h1>Say hello to akka-http</h1>"))
      }
    }
}

// Creating own settings
val settings = ServerSettings(ConfigFactory.load).withVerboseErrorMessages(true)
WebServer.startServer("localhost", 8080, settings)
Java
import akka.Done;
import akka.actor.ActorSystem;
import akka.http.javadsl.server.HttpApp;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.settings.ServerSettings;
import akka.http.javadsl.ServerBinding;
import com.typesafe.config.ConfigFactory;
import java.util.Optional;
import java.util.concurrent.*;

// Server definition
class MinimalHttpApp extends HttpApp {
  @Override
  protected Route routes() {
    return path("hello", () ->
      get(() ->
        complete("<h1>Say hello to akka-http</h1>")
      )
    );
  }
}

// Starting the server
final MinimalHttpApp myServer = new MinimalHttpApp();
final ServerSettings settings = ServerSettings.create(ConfigFactory.load()).withVerboseErrorMessages(true);
myServer.startServer("localhost", 8080, settings);

Providing your own Actor System

提供你自己的 Actor 系统

HttpAppHttpApp creates its own ActorSystemActorSystem instance when one is not provided. In case you already created an ActorSystemActorSystem in your application you can pass it to startServer as illustrated in the following example:

当没有提供 ActorSystem 时, HttpAppHttpApp 创建它自己的 ActorSystemActorSystem 实例

Scala
import akka.actor.ActorSystem
import akka.http.scaladsl.model._
import akka.http.scaladsl.server.HttpApp
import akka.http.scaladsl.server.Route

// Server definition
object WebServer extends HttpApp {
  override def routes: Route =
    path("hello") {
      get {
        complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, "<h1>Say hello to akka-http</h1>"))
      }
    }
}

// Starting the server
val system = ActorSystem("ownActorSystem")
WebServer.startServer("localhost", 8080, system)
system.terminate()
Java
import akka.Done;
import akka.actor.ActorSystem;
import akka.http.javadsl.server.HttpApp;
import akka.http.javadsl.server.Route;
import java.util.Optional;
import java.util.concurrent.*;

// Server definition
class MinimalHttpApp extends HttpApp {
  @Override
  protected Route routes() {
    return path("hello", () ->
      get(() ->
        complete("<h1>Say hello to akka-http</h1>")
      )
    );
  }
}

// Starting the server
final ActorSystem system = ActorSystem.apply("myOwn");
new MinimalHttpApp().startServer("localhost", 8080, system);
// ActorSystem is not terminated after server shutdown
// It must be manually terminated
system.terminate();

When you provide your own ActorSystemActorSystem you are responsible for terminating it. For more fine-grained control over the shutdown of various parts of the application, take a look at Coordinated ShutdownCoordinated Shutdown extension which is available since Akka 2.5.0.

当你提供自己的 ActorSystemActorSystem 时你有责任终止它。要更细粒度的控制应用程序各个部分的关闭,请查看从 Akka 2.5.0 开始可用的 [协调关闭]协调关闭 扩展。

Providing your own Actor System and Settings

提供你自己的 Actor 系统和设置

HttpAppHttpApp offers another overloaded startServer method where you can pass, on top of the host and port, your previously created ActorSystemActorSystem and your custom ServerSettingsServerSettings. You can see an example in the following code snippet:

HttpAppHttpApp 提供另一个重载的 startServer 方法,你可以在 hostport 之上传递先前创建的 ActorSystemActorSystem 和 自定义 ServerSettingsServerSettings 。 你可以在下面代码片段中看到示例:

Scala
import akka.actor.ActorSystem
import akka.http.scaladsl.model._
import akka.http.scaladsl.server.HttpApp
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.settings.ServerSettings
import com.typesafe.config.ConfigFactory

// Server definition
object WebServer extends HttpApp {
  override def routes: Route =
    path("hello") {
      get {
        complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, "<h1>Say hello to akka-http</h1>"))
      }
    }
}

// Starting the server
val system = ActorSystem("ownActorSystem")
val settings = ServerSettings(ConfigFactory.load).withVerboseErrorMessages(true)
WebServer.startServer("localhost", 8080, settings, system)
system.terminate()
Java
import akka.Done;
import akka.actor.ActorSystem;
import akka.http.javadsl.server.HttpApp;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.settings.ServerSettings;
import akka.http.javadsl.ServerBinding;
import com.typesafe.config.ConfigFactory;
import java.util.Optional;
import java.util.concurrent.*;

// Server definition
class MinimalHttpApp extends HttpApp {
  @Override
  protected Route routes() {
    return path("hello", () ->
      get(() ->
        complete("<h1>Say hello to akka-http</h1>")
      )
    );
  }
}

// Starting the server
final ActorSystem system = ActorSystem.apply("myOwn");
final ServerSettings settings = ServerSettings.create(ConfigFactory.load()).withVerboseErrorMessages(true);
new MinimalHttpApp().startServer("localhost", 8080, settings, system);
// ActorSystem is not terminated after server shutdown
// It must be manually terminated
system.terminate();

Overriding Termination Signal

覆盖终止信号

As already described previously, the default trigger that shuts down the server is pressing ENTER. For simple examples this is sufficient, but for bigger applications this is, most probably, not what you want to do. HttpAppHttpApp can be configured to signal the server termination just by overriding the method waitForShutdownSignal. This method must return a FutureCompletionStage that, when terminated, will shutdown the server.

如前所述,关闭服务器的默认触发器是按 ENTER。对于简单的示例,这已足够,但是对于较大的应用程序,这很可能不是想要执行的操作。 可以将 HttpAppHttpApp 配置为仅通过覆盖方法 waitForShutdownSignal 来发出服务器终止信号。 此方法必须返回一个 FutureCompletionStage ,当 Future 终止时,将关闭服务器。

This following example shows how to override the default termination signal:

下面例子显示怎样覆盖默认终止信号:

Scala
import akka.Done
import akka.actor.ActorSystem
import akka.http.scaladsl.model._
import akka.http.scaladsl.server.HttpApp
import akka.pattern
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.settings.ServerSettings
import com.typesafe.config.ConfigFactory
import scala.concurrent.duration._
import scala.concurrent.{ ExecutionContext, Future }
import scala.language.postfixOps

// Server definition
object WebServer extends HttpApp {
  override def routes: Route =
    path("hello") {
      get {
        complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, "<h1>Say hello to akka-http</h1>"))
      }
    }

  override def waitForShutdownSignal(actorSystem: ActorSystem)(implicit executionContext: ExecutionContext): Future[Done] = {
    pattern.after(5 seconds, actorSystem.scheduler)(Future.successful(Done))
  }
}

// Starting the server
WebServer.startServer("localhost", 8080, ServerSettings(ConfigFactory.load))
Java
import akka.Done;
import akka.actor.ActorSystem;
import akka.http.javadsl.server.HttpApp;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.settings.ServerSettings;
import akka.http.javadsl.ServerBinding;
import com.typesafe.config.ConfigFactory;
import java.util.Optional;
import java.util.concurrent.*;
import scala.concurrent.duration.Duration;
import scala.runtime.BoxedUnit;

import static akka.pattern.PatternsCS.after;

// Server definition
class SelfDestroyingHttpApp extends HttpApp {

  @Override
  protected Route routes() {
    return path("hello", () ->
      get(() ->
          complete("<h1>Say hello to akka-http</h1>")
      )
    );
  }

  @Override
  protected CompletionStage<Done> waitForShutdownSignal(ActorSystem system) {
    return after(Duration.apply(5, TimeUnit.SECONDS),
      system.scheduler(),
      system.dispatcher().prepare(),
      CompletableFuture.completedFuture(Done.getInstance()));
  }
}

// Starting the server
final SelfDestroyingHttpApp myServer = new SelfDestroyingHttpApp();
myServer.startServer("localhost", 8080, ServerSettings.create(ConfigFactory.load()));

Here the termination signal is defined by a future that will be automatically completed after 5 seconds.

这里终止信号由一个 future 定义,它将在 5 秒后自动完成。

Getting Notified on Server Shutdown

服务器关闭时得到通知

There are some cases in which you might want to clean up any resources you were using in your server. In order to do this in a coordinated way, you can override HttpAppHttpApp’s postServerShutdown method.

在某些情况下,你可能希望清理服务器中正在使用的所有资源。为了以协调的方式进行,可以覆盖 HttpAppHttpApppostServerShutdown 方法。

Here you can find an example:

你可以在这里找到示例:

Scala
import akka.Done
import akka.actor.ActorSystem
import akka.http.scaladsl.model._
import akka.http.scaladsl.server.HttpApp
import akka.http.scaladsl.server.Route
import akka.http.scaladsl.settings.ServerSettings
import scala.util.Try
import com.typesafe.config.ConfigFactory

// Server definition
class WebServer extends HttpApp {
  override def routes: Route =
    path("hello") {
      get {
        complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, "<h1>Say hello to akka-http</h1>"))
      }
    }

  private def cleanUpResources(): Unit = ???

  override def postServerShutdown(attempt: Try[Done], system: ActorSystem): Unit = {
    cleanUpResources()
  }
}

// Starting the server
new WebServer().startServer("localhost", 8080, ServerSettings(ConfigFactory.load))
Java
import akka.Done;
import akka.actor.ActorSystem;
import akka.http.javadsl.server.HttpApp;
import akka.http.javadsl.server.Route;
import akka.http.javadsl.settings.ServerSettings;
import akka.http.javadsl.ServerBinding;
import com.typesafe.config.ConfigFactory;
import java.util.Optional;
import java.util.concurrent.*;

// Server definition
class PostShutdownOverrideHttpApp extends HttpApp {

  @Override
  protected Route routes() {
    return path("hello", () ->
      get(() ->
        complete("<h1>Say hello to akka-http</h1>")
      )
    );
  }

  private void cleanUpResources() {
  }

  @Override
  protected void postServerShutdown(Optional<Throwable> failure, ActorSystem system) {
    cleanUpResources();
  }
}

// Starting the server
ActorSystem system = ActorSystem.apply("myActorSystem");
new PostShutdownOverrideHttpApp().startServer("localhost", 8080, ServerSettings.create(system), system);

The postServerShutdown method will be only called once the server attempt to shutdown has completed. Please notice that in the case that unbind fails to stop the server, this method will also be called with a failed Try.exception that this method is called with, may be null. It will be a non-null one only when unbind fails to stop the server.

只在服务器尝试关闭完成后才调用 postServerShutdown 方法。请注意, unbind 无法停止服务器的情况下,该方法也将使用一个错误的 Try 调用。 unbind 无法停止服务器时,failure 内部的 Throwablenull

在此文档中发现错误?该页面的源代码可以在 这里 找到。欢迎随时编辑并提交 Pull Request。