如何使用 ActionBuilder 和 Action 组合处理错误?
How can I handle errors using ActionBuilder, and Action composition?
我有两个操作:
object ErrorHandler extends
ActionBuilder[Request]{
def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
try {
block(request)
} catch {
case ex: Throwable => Future.successful{
InternalServerError(
Json.obj(
"status" -> JsString("error")
)
)
}
}
}
}
还有一个动作:
object WithFieldAction extends
ActionBuilder[WithFieldRequest] with ActionTransformer[Request, WithFieldRequest] {
val FIELD = "field"
def transform[A](request: Request[A]) = Future.successful {
new WithFieldRequest(request.getQueryString(FIELD), request)
}
}
我结合了这个动作:
def index = (ErrorHandler andThen WithFieldAction) { implicit request =>
1 / 0
}
但是 ErrorHandler
没有捕捉到异常,我看到了默认的错误页面。我该如何解决? (我不能使用全局错误处理程序,因为我想为不同的端点组使用不同的处理程序)
问题是异常在 Future
内抛出并保留。这意味着当你调用 block(request)
时,它只是去 return 一个 Future[Result]
来包装最终的异常(一个失败的 Future
)。 Future
不应该让异常逃脱它,所以包装在 try/catch 中不会做任何事情。
相反,您需要 recover
Future
。
def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
block(request) recover { ex: Throwable =>
InternalServerError(
Json.obj(
"status" -> JsString("error")
)
)
}
}
recover
接受 PartialFunction[Throwable, ?]
,因此您可以根据需要对异常进行细粒度处理。例如,您可以只恢复 java.lang.ArithmeticException
,如果您愿意,可以让所有其他故障传播到 Play 的错误处理。
我有两个操作:
object ErrorHandler extends
ActionBuilder[Request]{
def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
try {
block(request)
} catch {
case ex: Throwable => Future.successful{
InternalServerError(
Json.obj(
"status" -> JsString("error")
)
)
}
}
}
}
还有一个动作:
object WithFieldAction extends
ActionBuilder[WithFieldRequest] with ActionTransformer[Request, WithFieldRequest] {
val FIELD = "field"
def transform[A](request: Request[A]) = Future.successful {
new WithFieldRequest(request.getQueryString(FIELD), request)
}
}
我结合了这个动作:
def index = (ErrorHandler andThen WithFieldAction) { implicit request =>
1 / 0
}
但是 ErrorHandler
没有捕捉到异常,我看到了默认的错误页面。我该如何解决? (我不能使用全局错误处理程序,因为我想为不同的端点组使用不同的处理程序)
问题是异常在 Future
内抛出并保留。这意味着当你调用 block(request)
时,它只是去 return 一个 Future[Result]
来包装最终的异常(一个失败的 Future
)。 Future
不应该让异常逃脱它,所以包装在 try/catch 中不会做任何事情。
相反,您需要 recover
Future
。
def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
block(request) recover { ex: Throwable =>
InternalServerError(
Json.obj(
"status" -> JsString("error")
)
)
}
}
recover
接受 PartialFunction[Throwable, ?]
,因此您可以根据需要对异常进行细粒度处理。例如,您可以只恢复 java.lang.ArithmeticException
,如果您愿意,可以让所有其他故障传播到 Play 的错误处理。