繁体   English   中英

Scala播放-Action.async与BodyParser-异常处理

[英]Scala Play - Action.async with BodyParser - Exception Handling

我正在将Scala与Play一起用于我的微服务。 它具有一个Controller,该Controller将Action.async构造与自定义主体解析器一起使用。 这是一个示例代码:

def crud(param: String) = Action.async(SomeCustomBodyParser) { implicit request =>
    try {
      <some code>
    } catch {
      case _ => <Exception Handling logic>
    }
}

此代码的问题在于,如果SomeCustomBodyParser中发生异常,则不会在catch块中对其进行处理。 我尝试了几种方法,将其提取到外部然后手动进行处理,但是未正确捕获异常。 Action.async代码建议使用代码块并在单独的上下文中执行。 我不清楚它是如何工作的。

如何处理异常并发出更好的异常消息。

必须给Action.async一个Future[Result] ,可以通过成功的Result或失败的Result来完成。

任何failed Future都会导致错误的HTTP响应。

Action.async { Future.failed(new Exception("Foo") }

可以格式化这种错误的格式。

这里的问题是您试图使用同步错误处理程序来处理异步错误。 try catch只能处理同步错误。 Future[_]本质上是异步的,它会在您的try catch语句已经执行后(可能在其他线程中)引发错误(如果有的话)。

相反,在scala中,我们通过使用scalaz中的OptionEither\\/类的数据结构来使错误处理变得明确。 所有这些包装器构成Monad。

在大多数异步服务器的设置,你要的是FutureEither内部(或右偏变种一样\\/从scalaz。)这样,你抽象的在两个asynchronity和错误处理。 由于两个包装器都是monad,因此可以使用Monad Transformers组合它们。 这是一个很深的主题,如果您不熟悉它,则需要大量学习,但是这种数据结构的要旨如下:

class Task[E, A] {
  def flatMap[U](f: A => Task[E, U]): Task[E, U] = ??? // Use monad transformer here.
}

其中E代表您的自定义错误的类型-您可能会通过代数数据类型(如带有大量case class sealed trait来代表它们,而A是您的值类型。

如果您的BodyParser引发异常,或由于其他原因失败,则Action内的任何代码都不会执行。 async的性质在这里无关紧要。

例如,以下代码中的System.exit永远不会运行,因为BodyParser 总是返回异常。

package controllers

import javax.inject.Inject

import play.api.mvc._

import scala.concurrent.Future

class Application @Inject() extends Controller {

  def crud(param: String) = Action.async(
    parse.error[String](Future.failed(new RuntimeException("oh noes!")))
  ) { req =>
    System.exit(0)
    ???
  }

}

此代码生成以下堆栈跟踪:

play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[RuntimeException: oh noes!]]
    at play.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:254) ~[play_2.11-2.4.0.jar:2.4.0]
    at play.api.http.DefaultHttpErrorHandler.onServerError(HttpErrorHandler.scala:180) ~[play_2.11-2.4.0.jar:2.4.0]

并且stacktrace表示有一个DefaultHttpErrorHandler ,它被BodyParser抛出的异常调用。

ScalaErrorHandling的文档提供了一些自定义或编写自己的示例。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM