§处理错误
HTTP 应用程序可以返回两种主要类型的错误 - 客户端错误和服务器错误。客户端错误表示连接的客户端执行了错误的操作,服务器错误表示服务器存在问题。
Play 在许多情况下会自动检测客户端错误 - 这些错误包括格式错误的标头值、不支持的内容类型以及对无法找到的资源的请求。Play 在许多情况下也会自动处理服务器错误 - 如果您的操作代码抛出异常,Play 会捕获此异常并生成一个服务器错误页面发送给客户端。
Play 通过 HttpErrorHandler
接口处理这些错误。它定义了两个方法,onClientError
和 onServerError
。
§在 JSON API 中处理错误
默认情况下,Play 以 HTML 格式返回错误。
对于 JSON API,以 JSON 格式返回错误更一致。
Play 提供了一个名为 JsonHttpErrorHandler
的替代 HttpErrorHandler
实现,它将以 JSON 格式返回错误。
要使用该 HttpErrorHandler
实现,您应该在 application.conf
中配置 play.http.errorHandler
配置属性,如下所示
play.http.errorHandler = play.http.JsonHttpErrorHandler
§同时使用 HTML 和 JSON 以及其他内容类型
如果您的应用程序同时使用 HTML 和 JSON,就像现代 Web 应用程序中常见的那样,Play 提供了另一个错误处理程序,它根据客户端 Accept
标头中指定的偏好,委托给 HTML 或 JSON 错误处理程序。这可以通过以下方式指定
play.http.errorHandler = play.http.HtmlOrJsonHttpErrorHandler
对于大多数应用程序来说,这是一个合适的默认错误处理程序选择。
最后,如果您想除了 HTML 和 JSON 之外,还支持其他内容类型的错误,您可以扩展 PreferredMediaTypeHttpErrorHandler
并为特定内容类型添加错误处理程序,然后指定一个自定义错误处理程序,如下所述。
§提供自定义错误处理程序
如果您使用 BuiltInComponents
来构建您的应用程序,请覆盖 httpRequestHandler
方法以返回您自定义处理程序的实例。
如果您使用运行时依赖注入(例如 Guice),则错误处理程序可以在运行时动态加载。最简单的方法是在根包中创建一个名为 ErrorHandler
的类,该类实现 HttpErrorHandler
,例如
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import javax.inject.Singleton;
import play.http.HttpErrorHandler;
import play.mvc.*;
import play.mvc.Http.*;
@Singleton
public class ErrorHandler implements HttpErrorHandler {
public CompletionStage<Result> onClientError(
RequestHeader request, int statusCode, String message) {
return CompletableFuture.completedFuture(
Results.status(statusCode, "A client error occurred: " + message));
}
public CompletionStage<Result> onServerError(RequestHeader request, Throwable exception) {
return CompletableFuture.completedFuture(
Results.internalServerError("A server error occurred: " + exception.getMessage()));
}
}
如果您不想将您的错误处理程序放在根包中,或者如果您希望能够为不同的环境配置不同的错误处理程序,您可以通过在 application.conf
中配置 play.http.errorHandler
配置属性来实现这一点
play.http.errorHandler = "com.example.ErrorHandler"
§扩展默认错误处理程序
开箱即用,Play 的默认错误处理程序提供了许多有用的功能。例如,在开发模式下,当发生服务器错误时,Play 将尝试定位并渲染应用程序中导致该异常的代码片段,以便您可以快速查看并识别问题。您可能希望在生产环境中提供自定义服务器错误,同时仍然在开发环境中保持该功能。为了方便起见,Play 提供了一个 DefaultHttpErrorHandler
,它具有一些您可以覆盖的便利方法,以便您可以将自定义逻辑与 Play 的现有行为混合在一起。
例如,要仅在生产环境中提供自定义服务器错误消息,而保持开发错误消息不变,并且您还想提供一个特定的禁止错误页面
import com.typesafe.config.Config;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import javax.inject.*;
import play.*;
import play.api.OptionalSourceMapper;
import play.api.UsefulException;
import play.api.routing.Router;
import play.http.DefaultHttpErrorHandler;
import play.mvc.*;
import play.mvc.Http.*;
@Singleton
public class ErrorHandler extends DefaultHttpErrorHandler {
@Inject
public ErrorHandler(
Config config,
Environment environment,
OptionalSourceMapper sourceMapper,
Provider<Router> routes) {
super(config, environment, sourceMapper, routes);
}
protected CompletionStage<Result> onProdServerError(
RequestHeader request, UsefulException exception) {
return CompletableFuture.completedFuture(
Results.internalServerError("A server error occurred: " + exception.getMessage()));
}
protected CompletionStage<Result> onForbidden(RequestHeader request, String message) {
return CompletableFuture.completedFuture(
Results.forbidden("You're not allowed to access this resource."));
}
}
查看完整的 DefaultHttpErrorHandler
API 文档,了解可覆盖的方法以及如何利用它们。
下一步:测试您的应用程序
发现此文档中的错误? 此页面的源代码可在 此处 找到。 阅读完 文档指南 后,请随时贡献拉取请求。 有问题或建议要分享? 前往 我们的社区论坛 与社区进行交流。