revel框架自定义404页面需同时满足run.mode = prod、conf/app.conf中未注释的results.error.404 = 404.html(含空格)、模板位于app/views/errors/404.html三者,缺一不可;dev模式下强制绕过,仅显示调试堆栈。

Revel 框架的 404 页面不是靠模板引擎自动渲染的,它依赖 run.mode = prod + results.error.404 配置 + 特定路径的 404.html 模板三者同时生效;dev 模式下无论如何配置都不会触发自定义 404,只会显示调试堆栈或空白页。
为什么访问不存在路由时没看到自定义 404 页面
最常见原因是当前运行在 dev 模式。Revel 硬性规定:只有 run.mode = prod 且 conf/app.conf 中存在未注释的 results.error.404 = 404.html(等号两侧必须有空格),才会走自定义错误页流程。
- 检查终端启动日志是否含
Running in 'prod' mode;若显示dev,说明app.conf顶部的run.mode被后续区块覆盖了 -
results.error.404必须写在[prod]或[dev]区块内,不能放在全局区 - 值必须是纯文件名
404.html,不接受errors/404.html、404.tpl或任何带路径/扩展名变体 - 模板文件必须放在
app/views/errors/404.html,Revel 不会自动创建errors/目录,手误放错位置等于没写
如何写出能正确继承布局的 404.html 模板
直接写 HTML 会导致样式丢失、导航栏消失、JS/CSS 不加载——因为 Revel 的模板继承机制被绕过了。你必须显式调用标准布局片段。
- 开头必须有
{{set . "title" "Page Not Found"}},否则header.html可能渲染空 title - 必须包含
{{template "header.html" .}}和{{template "footer.html" .}},顺序不能颠倒 - 不要用
{{template "base.html" .}}替代,Revel 默认不提供base.html,这是常见误配点 - 内容区域建议包裹在语义化容器里,例如
<div class="error-page">...</div>,方便 CSS 定制
最小可行示例:
{{set . "title" "Page Not Found"}}{{template "header.html" .}}<div class="error-page">
<h1>Oops! You're lost.</h1>
<p>The page you requested doesn't exist.</p>
<a href="/">Go Home</a>
</div>{{template "footer.html" .}}
验证 404 渲染链路是否真正打通
手动访问一个明显不存在的路径(如 /nonexistent)只是第一步;你还得确认响应头状态码是 404,且模板内容确实被解析执行,而非返回原始 HTML 字符串。
- 用
curl -I http://localhost:9000/nonexistent检查响应头,确保含HTTP/1.1 404 Not Found,不是 200 或 500 - 查看浏览器开发者工具的 Network 标签页,确认返回内容是你的
404.html内容,而非框架默认 JSON:{"error":"Not Found"} - 如果看到白屏但响应码是 404,大概率是
404.html里引用了不存在的header.html或footer.html,导致模板解析失败后静默降级 - 删掉
tmp/目录并重启应用,可排除因旧编译缓存导致的模板未更新问题
容易被忽略的路径与权限细节
Revel 对 404 模板路径极其敏感,连目录层级和文件权限都可能让整个流程失效。
-
app/views/errors/目录权限需为 755,若为 700(仅属主可读),Revel 在 prod 模式下会跳过该目录扫描 - 文件名必须全小写
404.html,404.HTML或NotFound.html均无效 - 不能在
conf/app.conf中写results.error.404=404.html(无空格),Revel 解析器会忽略整行 - 如果你通过
revel.Server.Handler接入了外部http.ServeMux,要确保兜底处理器最后注册,否则/路径可能被 mux 拦截,Revel 根本收不到请求
真正的难点不在写模板,而在于三处配置(mode、conf、路径)必须严丝合缝对齐,漏掉任一空格或大小写,404 就不会出现。











