Revel 的错误页面默认不自动启用,需手动创建并配置:404 和 500 模板应置于 app/views/errors/404.html 和 app/views/errors/500.html,并通过 App.Error() 方法显式调用 RenderTemplate("errors/404.html") 渲染,同时必须设置 c.Response.Status。

Revel 的 error 页面默认放在哪
Revel 不像 Spring Boot 那样自动扫描 templates/error/ 目录。它的错误页面必须显式声明路径,且默认不启用静态 error 模板渲染——除非你手动配置或触发对应逻辑。
默认情况下,Revel 会返回纯文本错误(比如 404 Not Found),不会自动跳转到 HTML 页面。想让 404 或 500 显示自定义 HTML,得靠 App.Init 阶段注册错误处理器,或在 app/controllers/app.go 中覆盖 App.Error 方法。
- 错误模板文件应放在
app/views/errors/404.html和app/views/errors/500.html(注意是errors/,不是error/) - 路径大小写敏感,
Errors或ERRORS都不会被识别 - Revel 不会自动 fallback 到
404.html—— 它只响应你明确定义的Erroraction 返回的视图
怎么让 404 请求走自定义页面
Revel 的 404 不是“找不到路由就自动渲染 404.html”,而是:当 Router 找不到匹配路由时,会调用 App.Error 方法,并传入 revel.ERROR_404 错误码。你需要在这个方法里手动返回 RenderTemplate("errors/404.html")。
在 app/controllers/app.go 中添加或修改:
func (c App) Error() revel.Result {
switch c.Params.Route.Get("error") {
case revel.ERROR_404:
c.Response.Status = 404
return c.RenderTemplate("errors/404.html")
case revel.ERROR_500:
c.Response.Status = 500
return c.RenderTemplate("errors/500.html")
default:
c.Response.Status = 500
return c.RenderText("Server Error")
}
}
- 必须确保
c.Response.Status显式设为404或500,否则浏览器看到的是 200 状态码 -
RenderTemplate的路径是相对于app/views/的,所以写"errors/404.html",不是"app/views/errors/404.html" - 如果
routes文件里写了GET /{controller}/{action} {controller}.{action}这类兜底路由,它可能拦截本该 404 的请求,导致Error方法根本没机会执行
500 错误页面为什么总不生效
500 页面不生效,绝大多数情况是因为 panic 没被捕获进 Error 流程。Revel 默认会在中间件层 recover panic,并调用 App.Error,但前提是:你没在 controller action 里用 defer/recover 吞掉 panic,也没在 Init 阶段注册了冲突的 panic handler。
- 检查
app/init.go是否调用了revel.InterceptFunc或自定义revel.PanicHandler,它们可能绕过默认流程 - 确保
app/views/errors/500.html存在且语法合法;Go template 解析失败会导致二次 panic,陷入无限 500 循环 - 开发时开启
revel.DevMode = true(默认开启)会强制显示详细 panic 堆栈,掩盖你的 500 页面;上线前务必设为false - 若使用了自定义
revel.Interceptor,需确认它没有提前返回 result 或修改c.Response.Status
模板里怎么拿到错误信息
Revel 的 Error action 会把原始 error 对象注入模板上下文,变量名就是 .Error。你可以在 errors/404.html 或 errors/500.html 中直接访问:
{{if .Error}}<p>Error: {{.Error}}</p>{{end}}
-
.Error是error接口类型,可直接{{.Error}}输出字符串,但生产环境建议隐藏细节(尤其 500) - 不要依赖
.Status或.Code字段——Revel 不保证它们存在;状态码已由c.Response.Status控制 - 若需区分 404/500 场景做不同逻辑,推荐在
Error()方法中额外传参,比如c.Render("errors/404.html", revel.M{"type": "notfound"})
Revel 的错误页面机制是显式、可控的,但也因此容易漏掉关键步骤:状态码未设置、路径写错、DevMode 干扰、或 panic 被意外捕获。最常卡住的地方其实是 routes 里的兜底规则和 Init 阶段的拦截器冲突。











