[英]Scala future with akka-http
我需要用 akka-http 和 reactivemongo 編寫簡單的 web 服務。
保存數據的函數如下所示
def saveRoute(route: Route):Future[WriteResult] = {
collection.insert(route)
}
調用此函數的代碼如下所示
val userRoutes = {
logRequestResult("akka-http-microservice") {
path("routes") {
(post & entity(as[Route])) { route =>
Database.saveRoute(route)
}
}
}
}
我需要使用插入的 Route ID 返回結果,並在不讓線程等待的情況下執行此操作。 如果嘗試
Database.saveRoute(route).onComplete{
case Success(r) => complete(r.toString)
case Failure(e) => complete(e.getMessage)
}
它無法編譯,因為它不返回值。 我知道如何以骯臟的方式制作它,但真的想以適當的方式制作。
在這種情況下應該怎么做?
似乎我找到了最有效的方法來做到這一點。 它內置在 onComplete 指令中
(path("routes" / "add") & post & entity(as[Route])) {
route =>
onComplete(routesController.addRoute(route)) {
case Success(result) => complete(StatusCodes.Created, "OK")
case Failure(ex) => complete(new ErrorResponse(StatusCodes.InternalServerError.intValue, ErrorResponse.ERROR, ex.getMessage))
}
}
使用onSuccess
在未來完成時處理有效響應,在未來不成功時使用handleExceptions
處理。
val userRoutes = {
handleExceptions(mongoDbExceptionHandler) {
logRequestResult("akka-http-microservice") {
path("routes") {
(post & entity(as[Route])) { route =>
onSuccess(Database.saveRoute(route)) { result =>
complete(result)
}
}
}
}
}
}
// Something like this for whatever the exceptions you expect are
val mongoDbExceptionHandler = ExceptionHandler {
case ex: MongoDbReadException => complete(HttpResponse(InternalServerError, "No database")))
}
關於成功:http: //doc.akka.io/docs/akka/2.4.9/scala/http/routing-dsl/directives/future-directives/onSuccess.html
處理異常:http: //doc.akka.io/docs/akka/2.4.9/scala/http/routing-dsl/exception-handling.html
您可以映射未來,然后完成如下請求。
val future = Database.saveRoute(route)
val response = future.map(_.getId).recover(_.getMessage)
complete(response)
附帶說明一下,為了處理異常,最好有一個 ExceptionHandler 並將其包裝在您的路由中。 您可以在此處找到示例。
您幾乎沒有選擇,我將嘗試將最常用的選項用於基於 REST API 的解決方案:
OnSuccess 當你希望你的期望被expectionHandler冒泡和處理時使用它
concat(
path("success") {
onSuccess(Future { "Ok" }) { extraction =>
complete(extraction)
}
},
path("failure") {
onSuccess(Future.failed[String](TestException)) { extraction =>
complete(extraction)
}
}
)
https://doc.akka.io/docs/akka-http/current/routing-dsl/directives/future-directives/onSuccess.html
onComplete:當你想手動處理異常時。 嘗試包裹單子。
val route =
path("divide" / IntNumber / IntNumber) { (a, b) =>
onComplete(divide(a, b)) {
case Success(value) => complete(s"The result was $value")
case Failure(ex) => complete((InternalServerError, s"An error occurred: ${ex.getMessage}"))
}
}
https://doc.akka.io/docs/akka-http/current/routing-dsl/directives/future-directives/onComplete.html
這個怎么樣,替換:
Database.saveRoute(route)
和:
complete(Database.saveRoute(route).map(_.toString).recover(_.getMessage))
當您使用RequestContext
時,您應該使用以下內容:
import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server.RouteResult.{Complete, Rejected}
...
val myRoute: Route = (path("my-path") & get) { req: RequestContext =>
val futureResp: Future[HttpResponse] = ???
futureResp.map(resp => RouteResult.Complete(resp))
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.