Play 应用程序中的全局异常处理
Global Exception Handling in Play Application
目前我正在使用 Scala 和 Play 实现 REST API!框架。当用户提交的数据不正确,或者不允许用户查看资源时,API 必须使用 BadRequest 或 Forbidden 进行响应。
我不想用大量嵌套的 if-else 语句来检查每个权限。所以我只想引发 RuntimeExceptions,例如 BadRequestException 或 ForbiddenException。
class MapableRestException(msg: String) extends RuntimeException(msg)
class NotFoundException(msg: String) extends MapableRestException(msg)
class ForbiddenException(msg: String) extends MapableRestException(msg)
class BadRequestException(msg: String) extends MapableRestException(msg)
在全局 Class 中我覆盖了 onError
override def onError(request: RequestHeader, ex: Throwable): Future[Result] = ex.getCause match {
case notfound: NotFoundException => {
Future.successful(NotFound(JsonHelper.toJsonAll(ErrorDTO(notfound.getMessage()))).as(JSON))
}
case forbidden: ForbiddenException => {
Future.successful(Forbidden(JsonHelper.toJsonAll(ErrorDTO(forbidden.getMessage()))).as(JSON))
}
case badrequest: BadRequestException => {
Future.successful(BadRequest(JsonHelper.toJsonAll(ErrorDTO(badrequest.getMessage))).as(JSON))
}
case _ => super.onError(request, ex)
}
但是当抛出上述异常之一时,堆栈跟踪仍然打印在控制台上?
您好,
丹尼尔
我也对更直接的答案感兴趣,但与此同时,这里有一个解决方法。
创建一个 ActionBuilder
来运行你的块并使用 recover
(或 recoverWith
,如果你需要做异步的东西)来做你的全局错误处理,然后在Action
的位置:
object ActionWithErrorHandling extends ActionBuilder[Request] {
override def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]): Future[Result] = {
block(request) recover {
case e: PermissionDenied => Forbidden(e.getMessage)
case e: ItemNotFound => NotFound(e.getMessage)
}
}
}
在控制器中:
def myAction = ActionWithErrorHandling { implicit request =>
// Non-exception code path...
}
这可以说是一种更卫生的方法,因为它保留了真正的 oh-dear 情况下的全局 onError。
目前我正在使用 Scala 和 Play 实现 REST API!框架。当用户提交的数据不正确,或者不允许用户查看资源时,API 必须使用 BadRequest 或 Forbidden 进行响应。
我不想用大量嵌套的 if-else 语句来检查每个权限。所以我只想引发 RuntimeExceptions,例如 BadRequestException 或 ForbiddenException。
class MapableRestException(msg: String) extends RuntimeException(msg)
class NotFoundException(msg: String) extends MapableRestException(msg)
class ForbiddenException(msg: String) extends MapableRestException(msg)
class BadRequestException(msg: String) extends MapableRestException(msg)
在全局 Class 中我覆盖了 onError
override def onError(request: RequestHeader, ex: Throwable): Future[Result] = ex.getCause match {
case notfound: NotFoundException => {
Future.successful(NotFound(JsonHelper.toJsonAll(ErrorDTO(notfound.getMessage()))).as(JSON))
}
case forbidden: ForbiddenException => {
Future.successful(Forbidden(JsonHelper.toJsonAll(ErrorDTO(forbidden.getMessage()))).as(JSON))
}
case badrequest: BadRequestException => {
Future.successful(BadRequest(JsonHelper.toJsonAll(ErrorDTO(badrequest.getMessage))).as(JSON))
}
case _ => super.onError(request, ex)
}
但是当抛出上述异常之一时,堆栈跟踪仍然打印在控制台上?
您好, 丹尼尔
我也对更直接的答案感兴趣,但与此同时,这里有一个解决方法。
创建一个 ActionBuilder
来运行你的块并使用 recover
(或 recoverWith
,如果你需要做异步的东西)来做你的全局错误处理,然后在Action
的位置:
object ActionWithErrorHandling extends ActionBuilder[Request] {
override def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]): Future[Result] = {
block(request) recover {
case e: PermissionDenied => Forbidden(e.getMessage)
case e: ItemNotFound => NotFound(e.getMessage)
}
}
}
在控制器中:
def myAction = ActionWithErrorHandling { implicit request =>
// Non-exception code path...
}
这可以说是一种更卫生的方法,因为它保留了真正的 oh-dear 情况下的全局 onError。