How to create a custom 404 page handler with Play 2.0?

后端 未结 7 2157
故里飘歌
故里飘歌 2021-01-03 19:22

What’s the preferred way to handle 404 errors with Play 2.0 and show a nice templated view?

7条回答
  •  旧巷少年郎
    2021-01-03 19:56

    Please note that there are really two different problems to solve:

    1. Showing a custom 404 page when there is "no handler found", e.g. when the user goes to an invalid URL, and

    2. Showing a custom 404 (NotFound) page as a valid outcome of an existing handler.

    I think the OP was referring to #2 but answers referred to #1.

    "No Handler Found" Scenario

    In the first scenario, for "no handler found" (i.e. invalid URL), the other answers have it right but to be more detailed, per the Play 2.1 documentation as:

    Step 1: add a custom Global object:

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

    Step 2: add the template. Here's mine:

    @(path: String)
    
    
    
    

    Uh-oh. That wasn't found.

    @path

    Step 3: tweak your conf/application.conf to refer to your new "Global". I put it in the controllers package but it doesn't have to be:

    ...
    application.global=controllers.Global
    

    Step 4: restart and go to an invalid URL.

    "Real Handler can't find object" Scenario

    In the second scenario an existing handler wants to show a custom 404. For example, the user asked for object "1234" but no such object exists. The good news is that doing this is deceptively easy:

    Instead of Ok(), surround your response with NotFound()

    For example:

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

    What I like about this is the clean separation of the status code (200 vs 404) from the HTML returned (showFruit vs noSuchFruit).

    HTH Andrew

提交回复
热议问题