簡體   English   中英

Scala 未來與 akka-http

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM