【发布时间】:2012-04-16 21:09:32
【问题描述】:
使用 Play 2.0 处理 404 错误并显示漂亮的模板视图的首选方法是什么?
【问题讨论】:
使用 Play 2.0 处理 404 错误并显示漂亮的模板视图的首选方法是什么?
【问题讨论】:
您可以在 Global 对象上覆盖 onHandlerNotFound 方法,例如:
object Global extends GlobalSettings {
override def onHandlerNotFound(request: RequestHeader): Result = {
NotFound(views.html.notFound(request))
}
}
【讨论】:
views/ 目录中有一个notFound.scala.html 模板。
请注意,实际上有两个不同的问题需要解决:
当“未找到处理程序”时显示自定义 404 页面,例如当用户访问一个无效的 URL,并且
将自定义 404(未找到)页面显示为现有处理程序的有效结果。
我认为 OP 指的是 #2,但答案指的是 #1。
在第一种情况下,对于“未找到处理程序”(即无效 URL),其他答案是正确的,但要更详细,根据 Play 2.1 documentation 如下:
第 1 步:添加自定义全局对象:
import play.api._
import play.api.mvc._
import play.api.mvc.Results._
object Global extends GlobalSettings {
override def onHandlerNotFound(request: RequestHeader): Result = {
NotFound(
views.html.notFoundPage(request.path)
)
}
}
第 2 步:添加模板。这是我的:
@(path: String)
<html>
<body>
<h1>Uh-oh. That wasn't found.</h1>
<p>@path</p>
</body>
</html>
第 3 步:调整 conf/application.conf 以引用新的“全局”。我把它放在控制器包中,但不一定是:
...
application.global=controllers.Global
第 4 步:重新启动并转到无效的 URL。
在第二种情况下,现有处理程序想要显示自定义 404。例如,用户请求对象“1234”但不存在此类对象。好消息是,这样做看似简单:
用 NotFound() 代替 Ok()
例如:
object FruitController extends Controller {
def showFruit(uuidString: String) = Action {
Fruits.find(uuidString) match {
case Some(fruit) => Ok(views.html.showFruit(fruit))
// NOTE THE USE OF "NotFound" BELOW!
case None => NotFound(views.html.noSuchFruit(s"No such fruit: $uuidString"))
}
}
}
我喜欢的是状态代码(200 与 404)与返回的 HTML(showFruit 与 noSuchFruit)的清晰分离。
HTH 安德鲁
【讨论】:
Global 对象放在根包中,即 app/views/Global.scala 而不是 app/views/controllers/Global.scala 就像您的示例中一样,您可以跳过步骤 3 .默认的 application.conf 指向那里:# application.global=Global
如果你想使用 Java 而不是 Scala 来做同样的事情,你可以这样做(这适用于 play framework 2.0.3):
Global.java:
import play.GlobalSettings;
import play.mvc.Result;
import play.mvc.Results;
import play.mvc.Http.RequestHeader;
public class Global extends GlobalSettings {
@Override
public Result onHandlerNotFound(RequestHeader request) {
return Results.notFound(views.html.error404.render());
}
}
假设您的 404 错误模板是views.html.error404(即views/error404.scala.html)。
【讨论】:
这适用于 2.2.1。在 Global.java 中:
public Promise<SimpleResult> onHandlerNotFound(RequestHeader request) {
return Promise.<SimpleResult>pure(notFound(
views.html.throw404.render()
));
}
确保您有一个名为/views/throw404.scala.html的视图
【讨论】:
请注意,Play 开发团队正在努力摆脱 Play 中的全局状态,因此 GlobalSettings 和应用程序全局对象自 2.4 版以来已被弃用。
HttpErrorHandler.onClientError 应该被用来代替
GlobalSettings.onHandlerNotFound。基本上是创建一个继承自HttpErrorHandler的类,并为onClientError方法提供一个实现。
为了找出错误的类型(在您的情况下为 404),您需要读取状态代码,该代码作为方法参数之一传递,例如
if(statusCode == play.mvc.Http.Status.NOT_FOUND) {
// your code to handle 'page not found' situation
// e.g. return custom implementation of 404 page
}
为了让 Play 知道要使用什么处理程序,您可以将错误处理程序放在根包中,或者使用 play.http.errorHandler 配置键在 application.conf 中配置它,例如
play.http.errorHandler = "my.library.MyErrorHandler"
这适用于 2.2.3 Play - Java
public Promise<SimpleResult> onHandlerNotFound(RequestHeader request) {
return Promise<SimpleResult>pure(Results.notFound(views.html.notFound404.render()));
}
html 应该在 /views/notFound404.scala.html 中 不要忘记添加Results.notFounf()并导入play.mvc.Results;
【讨论】:
对于Java,如果你只想重定向到主页,我通过这个解决了。
@Override
public Promise<Result> onHandlerNotFound(RequestHeader request) {
return Promise.pure(redirect("/"));
}
【讨论】: