HttpApp 引导程序
HttpApp Bootstrap
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 HttpApp
HttpApp
is to help you start an HTTP server with just a few lines of code. This is accomplished just by extending HttpApp
HttpApp
and implementing the routes()
method. If desired, HttpApp
HttpApp
provides different hook methods that can be overridden to change its default behavior.
HttpApp
HttpApp
的目的是帮助你仅用几行代码行来启动一个 HTTP 服务器。通过扩展 HttpApp
HttpApp
并实例 routes
方法来完成。 如有需要, HttpApp
HttpApp
提供了不同的挂勾方法,可以将其重写以改变默认行为。
Please note that HttpApp
HttpApp
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 ActorSystem
ActorSystem
using Http.bindAndHandle
(which is also just a single line of code) is recommended over using HttpApp
HttpApp
.
请注意, HttpApp
HttpApp
不是启动 akka-http 服务器的权威方法。它是一种快速启动并运行的工具。 为了集成到已经提供了 ActorSystem
ActorSystem
的现有 Akka 应用程序中,建议使用 Http.bindAndHandle
(它也只有一行代码),而不使用 HttpApp
HttpApp
。
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 HttpApp
HttpApp
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 HttpApp
HttpApp
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
扩展 HttpApp
HttpApp
并实现这个服务器将处理的路由。 然后,我们通过提供 host
和 port
启动服务器。调用 startServer
阻塞当前线程直接服务器发出终止信息。 HttpApp
HttpApp
的默认行为是启动一个服务器,然后按 ENTER
后将其关闭。当对 startServer
的调用返回时,服务器已正确关闭。
Reacting to Bind Failures
应对绑定失败
HttpApp
HttpApp
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.
当初始化成功或失败后, HttpApp
HttpApp
提供了不同的挂勾被调用。例如:由于端口已被占用导致服务器无法启动或者该端口是一个特权端口。
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
提供你自己的服务器设置
HttpApp
HttpApp
reads the default ServerSettings
ServerSettings
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:
当没有提供 ServerSettings
ServerSettings
时, HttpApp
HttpApp
读取默认设置。你希望提供不同的设置,可以如例所示简单传递配置到 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 系统
HttpApp
HttpApp
creates its own ActorSystem
ActorSystem
instance when one is not provided. In case you already created an ActorSystem
ActorSystem
in your application you can pass it to startServer
as illustrated in the following example:
当没有提供 ActorSystem
时, HttpApp
HttpApp
创建它自己的 ActorSystem
ActorSystem
实例
- 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 ActorSystem
ActorSystem
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.
当你提供自己的 ActorSystem
ActorSystem
时你有责任终止它。要更细粒度的控制应用程序各个部分的关闭,请查看从 Akka 2.5.0 开始可用的 [协调关闭]协调关闭 扩展。
Providing your own Actor System and Settings
提供你自己的 Actor 系统和设置
HttpApp
HttpApp
offers another overloaded startServer
method where you can pass, on top of the host
and port
, your previously created ActorSystem
ActorSystem
and your custom ServerSettings
ServerSettings
. You can see an example in the following code snippet:
HttpApp
HttpApp
提供另一个重载的 startServer
方法,你可以在 host
和 port
之上传递先前创建的 ActorSystem
ActorSystem
和 自定义 ServerSettings
ServerSettings
。 你可以在下面代码片段中看到示例:
- 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. HttpApp
HttpApp
can be configured to signal the server termination just by overriding the method waitForShutdownSignal
. This method must return a Future
CompletionStage
that, when terminated, will shutdown the server.
如前所述,关闭服务器的默认触发器是按 ENTER
。对于简单的示例,这已足够,但是对于较大的应用程序,这很可能不是想要执行的操作。 可以将 HttpApp
HttpApp
配置为仅通过覆盖方法 waitForShutdownSignal
来发出服务器终止信号。 此方法必须返回一个 Future
CompletionStage
,当 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 HttpApp
HttpApp
’s postServerShutdown
method.
在某些情况下,你可能希望清理服务器中正在使用的所有资源。为了以协调的方式进行,可以覆盖 HttpApp
HttpApp
的 postServerShutdown
方法。
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
内部的 Throwable
为 null
。