[英]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中的Option
或Either
或\\/
类的数据结构来使错误处理变得明确。 所有这些包装器构成Monad。
在大多数异步服务器的设置,你要的是Future
与Either
内部(或右偏变种一样\\/
从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.