往往,我们的博客并不会包含所有的路由,也就是说,我们只有特定的几个路由,如果用户随便输入了一个路径地址,我们没有控制器来处理,那么程序就会抛出一个404,为了美观,也样式的统一,我们一般需要自定义404页面。这时候,我们就需要从路由中拦截404,然后重新定义404页面了。
404错误页面的拦截和重定义
我们先在controller文件夹建立一个common.go文件,用来放一些公共的处理函数,如404的控制器,500错误的控制器等。
404控制器
package controller
import (
"github.com/kataras/iris/v12"
)
func NotFound(ctx iris.Context) {
ctx.View("errors/404.html")
}
然后在template文件夹中在创建一个errors文件夹,在errors文件夹中,创建一个404.html:
404.html
{% include "partial/header.html" %}
<div class="ErrorPage-container">
<div class="ErrorPage-text">
<h1 class="ErrorPage-title">404h1>
<p class="ErrorPage-subtitle">你似乎来到了没有知识存在的荒原p>
<a class="button-primary" href="/">
去往首页
a>
div>
div>
{% include "partial/footer.html" %}
上一节我们提到了模板片段,使用include引入,正好我们可以在这里用上。我们这个时候,可以将404页面的头部和尾部抽离到公共的地方去,在template文件夹中,建立一个partial文件夹,用来放代码片段,在partial文件夹中,建立一个header.html和footer.html
header.html
html>
<html>
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, viewport-fit=cover" />
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"/>
<meta name="applicable-device" content="mobile">
<title>{% if webInfo.Title %}{{webInfo.Title}} - {% endif %}{{SiteName}}title>
<link href="https://www.layuicdn.com/layui/css/layui.css" rel="stylesheet">
<link href="/static/css/app.css" rel="stylesheet">
head>
<body>
<div class="layui-header">
<div class="layui-container">
<a href="/"><div class="layui-logo">{{SiteName}}div>a>
<ul class="layui-nav layui-layout-left nav-list">
<li class="layui-nav-item{% if !webInfo.NavBar %} layui-this{% endif %}"><a href="/">博客首页a>li>
{% for item in categories %}
<li class="layui-nav-item{% if webInfo.NavBar == item.Id %} layui-this{% endif %}"><a href="/?category_id={{item.Id}}">{{item.Title}}a>li>
{% endfor %}
ul>
<ul class="layui-nav layui-layout-right">
{% if hasLogin %}
<li class="layui-nav-item"><a href="/article/publish">发布文章a>li>
<li class="layui-nav-item"><a href="/admin/logout">退出a>li>
{% else %}
<li class="layui-nav-item"><a href="/admin/login">登录a>li>
{% endif %}
ul>
div>
div>
header.html 代码片段中,我们统一引入https://www.layuicdn.com/layui/css/layui.css
,layui是一个经典的前端框架,它已经给我们定义了很多常用的样式,我们借助它,可以省去很多前端样式的编写工作。
我们将自定义的控制页面样式文件,放到/static/css/app.css
文件中,static目录为网站的根目录,网站的根目录为public目录。以后我们不单独说明css文件,凡是涉及到html的样式控制,我们都将css卸载app.css
中。
因此,我们还需要将public目录在路由中,注册成为网站根目录,打开route/base.go,添加一行代码:
app.HandleDir("/", fmt.Sprintf("%spublic", config.ExecPath))
这样子,我们就可以通过浏览器访问到我们存放在public目录下的具体静态文件了。比如:http://127.0.0.1:8001/static/css/app.css
访问到的就是我们上面定义的自定义css文件。
这里我们顺便说一下,public
根目录下,我们定义static
为静态文件目录,里面有三个文件夹,一个是css文件夹,用来存放css文件,一个是js文件夹,用来存放js文件,一个是images文件夹,用来存放博客网站项目用到的图片文件。
public目录下,我们还定义了uploads
文件夹,用来存放通过前端上传的图片等文件。这个文件夹在git中是忽略的,因为它是从服务端上变化的文件夹。
footer.html
<div class="layui-trans layui-footer">
<div class="layui-container">
<div class="layout">irisweb 网站系统div>
<p>©2020 Fesion. All Rights Reservedp>
div>
div>
body>
<script src="https://www.layuicdn.com/layui/layui.js">script>
<script src="/static/js/app.js">script>
html>
我们将js文件放到footer.html 页脚代码片段中来。把js文件放在页脚加载会阻塞页面加载,如果js加载过慢,会导致页面长时间白屏,或者长时间无法晃动鼠标等假死状态。因此我们将js放在页面底部,让页面的dom加载完毕了再执行js操作。
这里我们引入了https://www.layuicdn.com/layui/layui.js
layui的js组件,它是layui前端框架必须的文件。layui 兼容人类正在使用的全部浏览器(IE6/7除外),可作为 PC 端后台系统与前台界面的速成开发方案。
我们将自定义的js文件,存放在/static/js/app.js
中,因为需要使用layui框架以及框架的组件,我们还需要用js来引入用到的组件。app.js
的代码初步为:
layui.use(['element', 'layedit', 'form', 'layer'], function(){
var $ = layui.$;
var element = layui.element;
var layedit = layui.layedit;
var form = layui.form;
var layer = layui.layer;
var editorIndex = null;
});
我们后面将用到element
、layedit
、form
、layer
这几个组件因此我们在这里先把他们注册了,后面就可以直接使用了。
注册404错误
我们再次打开route.go,在Register()函数中,添加上app.OnErrorCode(iris.StatusNotFound, controller.NotFound)
package route
import (
"github.com/kataras/iris/v12"
"irisweb/controller"
)
func Register(app *iris.Application) {
app.OnErrorCode(iris.StatusNotFound, controller.NotFound)
app.Get("/", controller.IndexPage)
}
这样子,我们就注册了404了,现在我们只有一个首页的路由,我们在浏览器访问其他任意路由,它都会输出我们定义的404错误页面了。
500错误输出
500错误,是程序内部错误,比如模板解析异常等,它就会抛出500错误,这时候,我们也要把它拦截下来,输出一个自定义的500错误信息给用户。
500控制器
我们在common.go 中个添加如下函数:
func InternalServerError(ctx iris.Context) {
errMessage := ctx.Values().GetString("error")
if errMessage == "" {
errMessage = "(Unexpected) internal server error"
}
ctx.ViewData("errMessage", errMessage)
ctx.View("errors/500.html")
}
ctx.Values() 是一个很有用的东西,主要用来使 处理方法与中间件 通信 记住真的很重要。ctx.Values().GetString("error") 获取自定义错误提示信息。
500.html
我们在errors文件夹下添加500.html文件:
{% include "partial/header.html" %}
<div class="ErrorPage-container">
<div class="ErrorPage-text">
<h1 class="ErrorPage-title">500h1>
<p class="ErrorPage-subtitle">系统给程序员提了一个bug,程序员正在修复中:{{errMessage}}p>
<a class="button-primary" href="/">
去往首页
a>
div>
div>
{% include "partial/footer.html" %}
注册500错误
我在打开route.go,在Register()函数中,添加上app.OnErrorCode(iris.StatusInternalServerError, controller.InternalServerError)
package route
import (
"github.com/kataras/iris/v12"
"irisweb/controller"
)
func Register(app *iris.Application) {
app.OnErrorCode(iris.StatusNotFound, controller.NotFound)
app.OnErrorCode(iris.StatusInternalServerError, controller.InternalServerError)
app.Get("/", controller.IndexPage)
}
这样子,我们就注册了500了,如果我们的模板有错误,它就会显示我们定义的500页面了。
完整的项目示例代码托管在GitHub上,需要查看完整的项目代码可以到github.com/fesiong/goblog 上查看,也可以直接fork一份来在上面做修改。