文档

§处理错误

HTTP 应用程序可以返回两种主要类型的错误 - 客户端错误和服务器错误。客户端错误表示连接的客户端做错了什么,服务器错误表示服务器存在问题。

Play 在许多情况下会自动检测客户端错误 - 这些错误包括格式错误的标头值、不支持的内容类型以及对无法找到的资源的请求。Play 在许多情况下也会自动处理服务器错误 - 如果您的操作代码抛出异常,Play 会捕获此异常并生成一个服务器错误页面发送给客户端。

Play 通过 HttpErrorHandler 接口处理这些错误。它定义了两个方法,onClientErroronServerError

§在 JSON API 中处理错误

默认情况下,Play 以 HTML 格式返回错误。
对于 JSON API,以 JSON 格式返回错误更一致。

Play 提供了一个名为 JsonHttpErrorHandler 的备用 HttpErrorHandler 实现,它将以 JSON 格式返回错误。

要使用该 HttpErrorHandler 实现,您应该在 application.conf 中配置 play.http.errorHandler 配置属性,如下所示

play.http.errorHandler = play.api.http.JsonHttpErrorHandler

§使用 HTML 和 JSON 以及其他内容类型

如果您的应用程序混合使用 HTML 和 JSON,就像现代 Web 应用程序中常见的那样,Play 提供了另一个错误处理程序,它根据客户端的 Accept 标头中指定的偏好委托给 HTML 或 JSON 错误处理程序。这可以通过以下方式指定:

play.http.errorHandler = play.api.http.HtmlOrJsonHttpErrorHandler

对于大多数应用程序来说,这是一个合适的默认错误处理程序选择。

最后,如果您想除了 HTML 和 JSON 之外,还支持其他内容类型的错误,您可以扩展 PreferredMediaTypeHttpErrorHandler 并指定一个自定义错误处理程序,如下所述。

§提供自定义错误处理程序

如果您使用 BuiltInComponents 来构建您的应用程序,请覆盖 httpErrorHandler 方法以返回您自定义处理程序的实例。

如果您使用运行时依赖注入(例如 Guice),则错误处理程序可以在运行时动态加载。最简单的方法是在根包中创建一个名为 ErrorHandler 的类,该类实现 HttpErrorHandler,例如

import javax.inject.Singleton

import scala.concurrent._

import play.api.http.HttpErrorHandler
import play.api.mvc._
import play.api.mvc.Results._

@Singleton
class ErrorHandler extends HttpErrorHandler {
  def onClientError(request: RequestHeader, statusCode: Int, message: String): Future[Result] = {
    Future.successful(
      Status(statusCode)("A client error occurred: " + message)
    )
  }

  def onServerError(request: RequestHeader, exception: Throwable): Future[Result] = {
    Future.successful(
      InternalServerError("A server error occurred: " + exception.getMessage)
    )
  }
}

如果您将错误处理程序放在根包(即无包)中并将其命名为 ErrorHandler,Play 将默认使用它。

但是,如果您想

然后在 application.conf 中添加配置属性 play.http.errorHandler,指向您的自定义错误处理程序类

play.http.errorHandler = "com.example.ErrorHandler"

如果您想使用客户端首选媒体类型的错误处理程序,并为另一种媒体类型添加您自己的错误处理程序,您可以扩展 PreferredMediaTypeHttpErrorHandler

import javax.inject._

import play.api.http._

class MyHttpErrorHandler @Inject() (
    jsonHandler: JsonHttpErrorHandler,
    htmlHandler: DefaultHttpErrorHandler,
    textHandler: MyTextHttpErrorHandler
) extends PreferredMediaTypeHttpErrorHandler(
      "application/json" -> jsonHandler,
      "text/html"        -> htmlHandler,
      "text/plain"       -> textHandler
    )

上面的示例使用 JSON 和 HTML 的默认 Play 处理程序,并添加了一个自定义处理程序,如果客户端更喜欢纯文本(例如,如果请求具有 Accept: text/plain),则将使用该处理程序。

§扩展默认错误处理程序

开箱即用,Play 的默认错误处理程序提供了许多有用的功能。例如,在开发模式下,当发生服务器错误时,Play 将尝试定位并渲染应用程序中导致该异常的代码段,以便您可以快速查看并识别问题。您可能希望在生产中提供自定义服务器错误,同时在开发中仍然保持该功能。为了方便这一点,Play 提供了一个 DefaultHttpErrorHandler,它具有一些您可以覆盖的便利方法,以便您可以将自定义逻辑与 Play 的现有行为混合使用。

例如,要仅在生产中提供自定义服务器错误消息,而保留开发错误消息不变,并且您还想提供一个特定的禁止错误页面

import javax.inject._

import scala.concurrent._

import play.api._
import play.api.http.DefaultHttpErrorHandler
import play.api.mvc._
import play.api.mvc.Results._
import play.api.routing.Router

@Singleton
class ErrorHandler @Inject() (
    env: Environment,
    config: Configuration,
    sourceMapper: OptionalSourceMapper,
    router: Provider[Router]
) extends DefaultHttpErrorHandler(env, config, sourceMapper, router) {
  override def onProdServerError(request: RequestHeader, exception: UsefulException) = {
    Future.successful(
      InternalServerError("A server error occurred: " + exception.getMessage)
    )
  }

  override def onForbidden(request: RequestHeader, message: String) = {
    Future.successful(
      Forbidden("You're not allowed to access this resource.")
    )
  }
}

查看 DefaultHttpErrorHandler 的完整 API 文档,以查看哪些方法可供覆盖,以及如何利用它们。

下一步:异步 HTTP 编程


发现文档中的错误?此页面的源代码可在此处找到。在阅读文档指南后,请随时贡献拉取请求。有疑问或建议要分享?前往我们的社区论坛与社区进行交流。