Play应用程序中的全局异常处理

时间:2015-02-12 13:50:54

标签: scala rest playframework playframework-2.0

目前我正在使用Scala和Play实现REST API!框架。当用户提交数据时,da不正确,或者不允许用户查看API必须使用BadRequest或Forbidden进行响应。

我不希望有大量的嵌套if-else语句来检查每个权限。所以我只想提出像BadRequestException或ForbiddenException这样的RuntimeExceptions。

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)

在Global 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)

}

但是当抛出上述异常中的一个时,堆栈跟踪仍会打印在控制台上?

问候, 丹尼尔

1 个答案:

答案 0 :(得分:4)

我也会对此更直接的回答感兴趣,但与此同时,这是一个解决方法。

创建运行您的块的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...
}

这可以说是一种更卫生的方法,因为它保留了全球onError的真实哦 - 亲爱的情况。