web-dev-qa-db-ja.com

Play 2.0でカスタム404ページハンドラーを作成するにはどうすればよいですか?

Play 2.0で404エラーを処理し、素敵なテンプレートビューを表示するための好ましい方法は何ですか?

27

onHandlerNotFound オブジェクトのGlobalメソッドをオーバーライドできます。例:

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

解決すべき2つの異なる問題があることに注意してください。

  1. 「ハンドラーが見つかりません」の場合にカスタム404ページを表示します。例:ユーザーが無効なURLにアクセスしたとき、および

  2. 既存のハンドラーの有効な結果としてカスタム404(NotFound)ページを表示します。

OPは#2を参照していたと思いますが、回答は#1を参照しています。

「ハンドラーが見つかりません」シナリオ

最初のシナリオでは、「ハンドラーが見つかりません」(つまり、無効なURL)の場合、他の回答は正しいですが、 Play 2.1ドキュメント のように詳細に説明します。

手順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に移動します。

「実際のハンドラーがオブジェクトを見つけることができません」シナリオ

2番目のシナリオでは、既存のハンドラーがカスタム404を表示したいと考えています。たとえば、ユーザーがオブジェクト「1234」を要求しましたが、そのようなオブジェクトは存在しません。良いニュースは、これを行うのは一見簡単だということです。

Ok()の代わりに、応答をNotFound()で囲みます

例えば:

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"))
    }
  }
}

これについて私が気に入っているのは、返されたHTML(showFruitとnoSuchFruit)からステータスコード(200と404)が明確に分離されていることです。

HTHアンドリュー

20
Andrew E

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)であると仮定します。

6

Play開発チームはPlayのグローバル状態から脱却するために多大な努力を払っているため、バージョン2.4以降、GlobalSettingsとアプリケーションGlobalオブジェクトは非推奨になっていることに注意してください。

HttpErrorHandler.onClientErrorの代わりにGlobalSettings.onHandlerNotFoundを使用する必要があります。基本的に、HttpErrorHandlerから継承するクラスを作成し、onClientErrorメソッドの実装を提供します。

エラーのタイプ(あなたの場合は404)を見つけるには、ステータスコードを読み取る必要があります。ステータスコードは、メソッド引数の1つとして渡されます。

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"

エラー処理の詳細については、 Scala または Java の場合を参照してください。

2
Tom

これは2.2.1で機能します。 Global.Javaの場合:

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

/views/throw404.scala.htmlというビューがあることを確認してください

2
Shanker Kaura

Javaの場合、メインページにリダイレクトするだけの場合は、これで解決しました。

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