如何使用Play 2.0创建自定义404页面处理程序?

时间:2012-04-03 08:10:45

标签: scala playframework-2.0

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

7 个答案:

答案 0 :(得分:23)

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

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

答案 1 :(得分:20)

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

  1. 当“找不到处理程序”时显示自定义404页面,例如当用户转到无效的网址时,

  2. 将自定义404(NotFound)页面显示为现有处理程序的有效结果。

  3. 我认为OP指的是#2,但答案是#1。

    “找不到处理程序”场景

    在第一个场景中,对于“找不到处理程序”(即无效的URL),其他答案是正确的,但要更详细,按Play 2.1 documentation为:

    步骤1:添加自定义Global对象:

    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:重新启动并转到无效的网址。

    “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 vs 404)与返回的HTML(showFruit vs noSuchFruit)完全分开。

    HTH 安德鲁

答案 2 :(得分:6)

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

答案 3 :(得分:2)

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

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

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

的视图

答案 4 :(得分:2)

请注意,Play开发团队正在努力摆脱Play中的全局状态,因此package com.example.siv.mahalaxmipetroleums; import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; public class DipToVol extends Fragment { Button clearButton11,calcButton11; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_one, container, false); clearButton11 = (Button) getView().findViewById(R.id.clearBtn1); calcButton11 = (Button) getView().findViewById(R.id.calcBtn1); calcButton11.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int dipHSD = 0, dipMS = 0; final short radHSD = 1219; final short lenHSD = 6810; final short radMS = 999; final short lenMS = 6804; double volHSD, volMS,volHSD1, volMS1; EditText dipH = (EditText) view.findViewById(R.id.dipHSD1); EditText dipM = (EditText) view.findViewById(R.id.dipMS1); TextView volH = (TextView) view.findViewById(R.id.volHSD1); TextView volM = (TextView) view.findViewById(R.id.volMS1); try { dipHSD = Integer.parseInt(dipH.getText().toString()); volHSD = calVol(radHSD, lenHSD, dipHSD); volHSD1 = Math.round(volHSD); volH.setText(volHSD1 + ""); } catch (NumberFormatException e) { volH.setText(""); } try{ dipMS = Integer.parseInt(dipM.getText().toString()); volMS = calVol(radMS, lenMS, dipMS); volMS1 = Math.round(volMS); volM.setText(volMS1 + ""); }catch(NumberFormatException e){volM.setText("");} } }); clearButton11.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { EditText dipH = (EditText) view.findViewById(R.id.dipHSD1); EditText dipM = (EditText) view.findViewById(R.id.dipMS1); TextView volH = (TextView) view.findViewById(R.id.volHSD1); TextView volM = (TextView) view.findViewById(R.id.volMS1); volH.setText(""); volM.setText(""); dipH.setText(""); dipM.setText(""); } }); return view; } public double calVol(short rad, short len, int height) { double area; area = (Math.PI * Math.pow(rad, 2) / 2) - Math.pow(rad, 2) * Math.asin(1 - (height / (double)rad)) - (rad - height) * Math.sqrt(height * (2 * rad - height)); return area*len*0.000001; } } 和应用程序Global对象自版本2.4以来已被弃用。

应该使用

GlobalSettings代替 HttpErrorHandler.onClientError。基本上创建一个继承自GlobalSettings.onHandlerNotFound的类,并为HttpErrorHandler方法提供实现。

为了找出错误类型(在你的情况下为404),你需要读取状态代码,它作为一个方法参数传递,例如。

onClientError

为了让Play了解要使用的处理程序,您可以将错误处理程序放在root包中,或者使用if(statusCode == play.mvc.Http.Status.NOT_FOUND) { // your code to handle 'page not found' situation // e.g. return custom implementation of 404 page } 配置键在application.conf中配置它。

play.http.errorHandler

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

答案 5 :(得分:0)

对于Java,如果你只想重定向到主页面,我就解决了这个问题。

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

答案 6 :(得分:-1)

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