手动调用 PlayFramework 自定义错误页面
Posted
技术标签:
【中文标题】手动调用 PlayFramework 自定义错误页面【英文标题】:Call manually PlayFramework custom error page 【发布时间】:2016-04-07 07:24:25 【问题描述】:我在 PlayFramework 中实现了自定义页面,就像文档中所说的那样:https://www.playframework.com/documentation/2.4.x/JavaErrorHandling
我在 application.conf 中添加了对 ErrorHandler 的引用
play.http.errorHandler = "com.company.ErrorHandler"
我自己实现了 ErrorHandler:
public class ErrorHandler extends DefaultHttpErrorHandler
@Inject
public ErrorHandler(Configuration configuration, Environment environment, OptionalSourceMapper sourceMapper, Provider<Router> routes)
super(configuration, environment, sourceMapper, routes);
@Override
public F.Promise<Result> onClientError(Http.RequestHeader requestHeader, int errorCode, String message)
Logger.debug("Error: onClientError : " + errorCode + ", message: " + message);
return super.onClientError(requestHeader, errorCode, message);
@Override
public F.Promise<Result> onServerError(Http.RequestHeader request, Throwable exception)
Logger.debug("Error: onServerError general");
return F.Promise.pure(redirect(com.company.routes.ErrorController.serverErrorPage()));
@Override
protected F.Promise<Result> onBadRequest(Http.RequestHeader request, String message)
Logger.debug("Error: onBadRequest, message: " + message);
return F.Promise.pure(redirect(com.company.routes.ErrorController.badRequestPage()));
@Override
protected F.Promise<Result> onForbidden(Http.RequestHeader request, String message)
Logger.debug("Error: onForbidden, message: " + message);
return F.Promise.pure(redirect(com.company.routes.ErrorController.forbiddenPage()));
@Override
protected F.Promise<Result> onNotFound(Http.RequestHeader request, String message)
Logger.debug("Error: onNotFound, message: " + message);
return F.Promise.pure(redirect(com.company.routes.ErrorController.notFoundPage()));
@Override
protected F.Promise<Result> onOtherClientError(Http.RequestHeader request, int statusCode, String message)
Logger.debug("Error: onOtherClientError, message: " + message);
return F.Promise.pure(redirect(com.company.routes.ErrorController.errorDefaultPage()));
当框架本身抛出错误时,自定义页面效果很好。
虽然我在从控制器重定向到错误页面时遇到问题。当我调用端点时:
public Result contact()
return Results.forbidden("Forbidden");
没有显示来自 ErrorHander 的错误页面。我只看到文字“禁止”。
如何在不显式重定向的情况下显示我的自定义错误页面?
【问题讨论】:
【参考方案1】:我遇到了类似的问题,我通过覆盖 onClientError 并切换到不同的 HTTP 状态代码来解决它:
public class ErrorHandler extends DefaultHttpErrorHandler
@Inject
public ErrorHandler(Configuration configuration, Environment environment,
OptionalSourceMapper sourceMapper, Provider<Router> routes)
super(configuration, environment, sourceMapper, routes);
@Override
public Promise<Result> onClientError(RequestHeader request, int statusCode,
String message)
switch (statusCode)
case Http.Status.BAD_REQUEST:
Logger.info(CLASS_NAME + ".onBadRequest: " + message);
return Promise.<Result> pure(
Results.badRequest(views.html.error.render("Bad request")));
case Http.Status.NOT_FOUND:
Logger.info(CLASS_NAME + ".onNotFound: Requested page \""
+ request.uri() + "\" couldn't be found.");
return Promise.<Result> pure(
Results.notFound(views.html.error.render("Requested page \""
+ request.uri() + "\" couldn't be found.")));
case Http.Status.FORBIDDEN:
Logger.info(CLASS_NAME + ".onForbidden: " + message);
return Promise.<Result> pure(Results
.forbidden("You're not allowed to access this resource."));
default:
Logger.info(CLASS_NAME + ".onClientError: HTTP status code "
+ statusCode + ", " + message);
return Promise.<Result> pure(Results.status(statusCode,
views.html.error.render("Internal server error")));
@Override
public Promise<Result> onServerError(RequestHeader request,
Throwable exception)
Logger.info(CLASS_NAME + ".onServerError: Internal server error",
exception);
return Promise.<Result> pure(Results.internalServerError(
views.html.error.render("Internal server error")));
也许它甚至是 Play 文档中的一个错误?至少在HttpErrorHandler
接口中,除了onServerError
或onClientError
(https://www.playframework.com/documentation/2.4.0/api/java/play/http/HttpErrorHandler.html) 之外,它没有谈论其他方法。
【讨论】:
这很好。但是,如果您检查 DefaultHttpErrorHandler 的底层实现,那么您会注意到它已经将 onClientError 中的调用重定向到其他方法,例如 for e.g. onBadRequest,onForbidden。我的问题是,尽管返回了结果。禁止()。自定义 ErrorHandler 未捕获该请求。 你似乎是对的。也许它适用于 Play 2.5 - 与 2.4 相比,它们在 DefaultHttpErrorHandler 中发生了很大变化。【参考方案2】:我找到了一种通过将客户端错误注入所需元素来直接调用客户端错误的方法。我最终得到了以下解决方案(Play Framework 2.5):
public class ErrorHandler extends DefaultHttpErrorHandler
private ErrorController errorController;
@Inject
public ErrorHandler(Configuration configuration,
Environment environment,
OptionalSourceMapper sourceMapper,
Provider<Router> routes,
ErrorController errorController)
super(configuration, environment, sourceMapper, routes);
this.errorController = errorController;
@Override
public CompletionStage<Result> onServerError(Http.RequestHeader request, Throwable exception)
Logger.debug("Error: onServerError general");
return CompletableFuture.completedFuture(this.errorController.serverErrorPage());
@Override
protected CompletionStage<Result> onBadRequest(Http.RequestHeader request, String message)
Logger.debug("Error: onBadRequest, message: " + message);
return CompletableFuture.completedFuture(this.errorController.badRequestPage());
@Override
protected CompletionStage<Result> onForbidden(Http.RequestHeader request, String message)
Logger.debug("Error: onForbidden, message: " + message);
return CompletableFuture.completedFuture(this.errorController.forbiddenPage());
@Override
protected CompletionStage<Result> onNotFound(Http.RequestHeader request, String message)
Logger.debug("Error: onNotFound, message: " + message);
return CompletableFuture.completedFuture(this.errorController.notFoundPage());
@Override
protected CompletionStage<Result> onOtherClientError(Http.RequestHeader request, int statusCode, String message)
Logger.debug("Error: onOtherClientError, message: " + message);
return CompletableFuture.completedFuture(this.errorController.errorDefaultPage());
那我可以这样称呼它:
class SomeElement
private final DefaultHttpErrorHandler errorHandler;
@Inject
public SomeElement(DefaultHttpErrorHandler errorHandler)
this.errorHandler = errorHandler;
public CompletionStage<Result> onAuthFailure(final Http.Context context,
final Optional<String> content)
return this.errorHandler.onClientError(context.request(), Http.Status.FORBIDDEN, "You don't have required permissions.");
【讨论】:
以上是关于手动调用 PlayFramework 自定义错误页面的主要内容,如果未能解决你的问题,请参考以下文章
playframework[1.2.4] 500个html页面
在 playframework 中重新加载自定义文件更改的应用程序
织梦CMS如何在自定义表单页调用arclist标签啊,怎么在自定义表单页调用无效!
如何解决直接自引用导致循环错误将ActorRef保存在playframework 2.4.6中的redis上