代码之家  ›  专栏  ›  技术社区  ›  Eric Kolotyluk

为什么Akka HTTP路由捕捉到我的异常?

  •  0
  • Eric Kolotyluk  · 技术社区  · 7 年前

    给定此代码

    def leaderboardPost(name: Option[String]): Route =
      post {
        logRequest("leaderboard", Logging.DebugLevel) {
          handleRejections(postBodyRejections) {
            entity(as[LeaderboardPostRequest]) { leaderboard =>
              try {
                complete(leaderboardCreate(Some(leaderboard.name), Some(leaderboard.kind)))
              } catch {
                case cause: DuplicateIDException =>
                  logger.error(cause)
                  complete(cause.response)
                case cause: UnknownKindException =>
                  logger.warn(cause)
                  complete(cause.response)
                case cause: Throwable =>
                  logger.error(cause)
                  complete(HttpResponse(InternalServerError, entity = s"Exception thrown from LeaderboardPost: ${cause.getMessage}"))
              }
            }
          }
        }
      }
    

    什么时候? leaderboardCreate 投掷 UnknownKindException 路由代码捕获它并将其转换为 Completing with 500 Internal Server Error response. To change default exception handling behavior, provide a custom ExceptionHandler.

    当我正在创建一个自定义的异常处理程序时,我不明白为什么需要这样做。我的代码应该捕获它并返回 complete(cause.response) 相反。Akka HTTP如何在我的代码之前捕获异常?

    1 回复  |  直到 7 年前
        1
  •  2
  •   SergGr    7 年前

    据我所知,这是因为 leaderboardCreate 实际上不是与 complete 如你所料打电话。这个 完成 方法返回 StandardRoute 延伸自 Route 定义为:

    type Route = RequestContext ⇒ Future[RouteResult]
    

    换句话说,“路由”是一个从上下文到 Future (指 RouteResult )如果你看 完成 定义如下:

    def complete(m: ⇒ ToResponseMarshallable): StandardRoute =
      StandardRoute(_.complete(m))
    

    注意 ⇒ 之前 ToResponseMarshallable . 这是传递参数 by name 这实际上把它变成了一个懒惰的评价。

    换句话说,你所有的 try/catch 包装是非常小(且无例外)的代码 标准德鲁特 它将您的逻辑捕获为一个懒惰的值,而不是逻辑本身的执行。这就是为什么你需要 custom ExceptionHandler 您(或者更确切地说,akka)可以将其放入错误处理程序链中, 未来 什么时候开始运行。

    推荐文章