【问题标题】:How to create a custom 404 page handler with Play 2.0?如何使用 Play 2.0 创建自定义 404 页面处理程序?
【发布时间】:2012-04-16 21:09:32
【问题描述】:

使用 Play 2.0 处理 404 错误并显示漂亮的模板视图的首选方法是什么?

【问题讨论】:

    标签: scala playframework-2.0


    【解决方案1】:

    您可以在 Global 对象上覆盖 onHandlerNotFound 方法,例如:

    object Global extends GlobalSettings {
      override def onHandlerNotFound(request: RequestHeader): Result = {
        NotFound(views.html.notFound(request))
      }
    }
    

    【讨论】:

    【解决方案2】:

    请注意,实际上有两个不同的问题需要解决:

    1. 当“未找到处理程序”时显示自定义 404 页面,例如当用户访问一个无效的 URL,并且

    2. 将自定义 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。

    “Real Handler 找不到对象”场景

    在第二种情况下,现有处理程序想要显示自定义 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
    • 在 Play 2.2 中,响应必须包装在 Future 中:playframework.com/documentation/2.2.x/ScalaGlobal
    【解决方案3】:

    如果你想使用 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)。

    【讨论】:

      【解决方案4】:

      这适用于 2.2.1。在 Global.java 中:

      public Promise<SimpleResult> onHandlerNotFound(RequestHeader request) {
          return Promise.<SimpleResult>pure(notFound(
              views.html.throw404.render()
          ));
      }
      

      确保您有一个名为/views/throw404.scala.html的视图

      【讨论】:

        【解决方案5】:

        请注意,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"
        

        您可以在此处找到有关处理错误的更多详细信息:ScalaJava

        【解决方案6】:

        这适用于 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;

        【讨论】:

        • 您的问题不包含该问题的至少一个其他答案尚未提供的任何信息。
        【解决方案7】:

        对于Java,如果你只想重定向到主页,我通过这个解决了。

        @Override
        public Promise<Result> onHandlerNotFound(RequestHeader request) {
            return Promise.pure(redirect("/"));
        }
        

        【讨论】:

          猜你喜欢
          • 2019-01-24
          • 1970-01-01
          • 2019-08-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多