框架的特性_Go 语言 Web 框架 Echo 系列:基础篇—通过一个例子串联各特性
通過前面的介紹,相信對 echo 有了一個初步的認識。本文我們通過一個簡單的登錄頁面來串聯 echo 的相關特性。因為該文主要關注各個特性,所以在目錄結構和代碼組織方面很隨意。
本節最終效果
1)登錄頁面
2)登錄失敗
3)登錄成功
main 函數骨架
使用 echo 框架,在程序入口處一般包含如下內容:
func?main()?{?//?創建?echo?實例
?e?:=?echo.New()
?//?配置日志
?configLogger(e)
?//?注冊靜態文件路由
?e.Static("img",?"img")
?e.File("/favicon.ico",?"img/favicon.ico")
?//?設置中間件
?setMiddleware(e)
?//?注冊路由
?RegisterRoutes(e)
?//?啟動服務
?e.Logger.Fatal(e.Start(":2019"))
}
日志
echo 中定義了一個接口:Logger,而 Echo 結構體有一個該接口的字段,這也就是 main 函數最后一句:e.Logger.Fatal 可以這么用的原因。框架中該接口的具體實現使用的是 github.com/labstack/gommon/log,如果需要,我們可以采用自己的實現,替換框架默認的。
默認情況下,日志輸出到終端,而且 Level 級別是 ERROR,我們可以方便的通過 Logger 接口提供的方法進行修改:
func?configLogger(e?*echo.Echo)?{?//?定義日志級別
?e.Logger.SetLevel(log.INFO)
?//?記錄業務日志
?echoLog,?err?:=?os.OpenFile("log/echo.log",?os.O_CREATE|os.O_WRONLY|os.O_APPEND,?0644)
?if?err?!=?nil?{
??panic(err)
?}
?//?同時輸出到文件和終端
?e.Logger.SetOutput(io.MultiWriter(os.Stdout,?echoLog))
}
為了方便,開發中我將日志同時輸出到了終端和文件中。
中間件
幾乎所有的 Web 框架都支持中間件。其實這里的中間件跟傳統的中間件不是一回事,這里的中間件其實是一種裝飾模式。閑言少敘,我們看看 Echo 的中間件。
以 Recover 中間件為例講解。
中間件標準簽名
通過 Echo.Use 方法知曉,中間件是 MiddlewareFunc 類型,它的定義如下:
type?MiddlewareFunc?func(echo.HandlerFunc)?echo.HandlerFunc也就是說,一個中間件應該是 MiddlewareFunc 類型。所以,一個函數,只要返回 MiddlewareFunc 類型就是一個 Echo 中間件。
func?Recover()?echo.MiddlewareFunc?{??...
}
支持配置的中間件
Echo 的中間件通常都支持以下功能:
- 通過配置修改中間件的行為
- 可以選擇是否跳過該中間件
一般做法就是:
- 定義一個類型,如:RecoverConfig,用于配置 Recover 中間件的行為;
- 給上述類型的一個默認實例:DefaultRecoverConfig;
- 定義一個支持傳遞配置的函數,返回中間件類型,如:RecoverWithConfig;
- 定義一個不帶參數的函數,返回中間件類型,內部調用帶參數的中間件函數,參數用默認實例,如:Recover,它的實現是直接調用 RecoverWithConfig(DefaultRecoverConfig);
我們的例子代碼中就通過配置修改了中間件行為:
//?access?log?輸出到文件中?accessLog,?err?:=?os.OpenFile("log/access.log",?os.O_CREATE|os.O_WRONLY|os.O_APPEND,?0644)
?if?err?!=?nil?{
??panic(err)
?}
?//?同時輸出到終端和文件
?middleware.DefaultLoggerConfig.Output?=?accessLog
?e.Use(middleware.Logger())
自己定義一個簡單中間件
很多時候,我們業務的中間件,不需要那么靈活,沒必要通過配置來控制行為,這時候可以像例子中的 AutoLogin 一樣:
//?AutoLogin?如果上次記住了,則自動登錄func?AutoLogin(next?echo.HandlerFunc)?echo.HandlerFunc?{
?return?func(ctx?echo.Context)?error?{
??cookie,?err?:=?ctx.Cookie("username")
??if?err?==?nil?&&?cookie.Value?!=?""?{
???//?實際項目這里可以通過?username?讀庫獲取用戶信息
???user?:=?&User{Username:?cookie.Value}
???//?放入?context?中
???ctx.Set("user",?user)
??}
??return?next(ctx)
?}
}
接收一個 echo.HandlerFunc 類型,同時返回一個 echo.HandlerFunc 類型,這就是 MiddlewareFunc 的定義,因此 AutoLogin 可以直接當中間件使用。注意:在使用是這里和上面 Recover 的區別,Recover 是返回一個中間件,而 AutoLogin 本身是一個中間件,因此使用時分別是:Use(Recover()) 和 Use(AutoLogin)。
在具體實現中間件時,可以在調用 next() 函數前后增加該中間件需要的功能。
Cookie 和 Session
關于 Cookie、Session 和 Token 的介紹,可以通過 《一文帶您徹底理解Cookie、Session、Token》?:(https://cloud.tencent.com/developer/article/1542456)了解下。
在 Go 中,Session 相關功能最常用的包是 github.com/gorilla/sessions。Echo 提供了 Session 中間件,使用的就是該包。這里我們主要講解一下登錄需要用到的功能。
登錄成功種 Cookie
//?用標準庫種?cookiecookie?:=?&http.Cookie{
??Name:?????"username",
??Value:????username,
??HttpOnly:?true,
}
if?rememberMe?==?"1"?{
??cookie.MaxAge?=?7*24*3600?//?7?天
}
ctx.SetCookie(cookie)
我們這里直接使用了標準庫的方式實現,而不是使用 ``github.com/gorilla/sessions` 包。默認情況下,瀏覽器關閉,cookie 刪除,當“記住我”,保存 7 天。這里留一個問題:cookie.Expires 和 cookie.MaxAge 的區別?
重定向保留用戶名
在登錄失敗后,為了避免用戶再次輸入用戶名,這里借用 github.com/gorilla/sessions 包的 Flash Message 功能。
github.com/gorilla/sessions 實現了 Cookie 和文件系統 Session,默認情況下,使用 Cookie。
sess?:=?getCookieSession(ctx)sess.AddFlash(username,?"username")
err?:=?sess.Save(ctx.Request(),?ctx.Response())
在讀 Flash Message 的地方,一定要注意,需要再次執行 session.Save:
sess?:=?getCookieSession(ctx)if?flashes?:=?sess.Flashes("username");?len(flashes)?>?0?{
??data["username"]?=?flashes[0]
}
sess.Save(ctx.Request(),?ctx.Response())
總結
一個簡單的登錄,涉及到的知識點還是不少的,但依然有不少 Echo 框架的功能沒包括。后面我們會介紹更多 Echo 的特性和功能,這個簡單的例子,希望能夠讓你對 Echo 更有感覺。
完整示例代碼:https://github.com/polaris1119/echo-login-example
覺得不錯,歡迎關注:
點個贊、在看和轉發是最大的支持
總結
以上是生活随笔為你收集整理的框架的特性_Go 语言 Web 框架 Echo 系列:基础篇—通过一个例子串联各特性的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ios图文详情加载html_前端项目00
- 下一篇: 古风一棵桃花树简笔画_为什么,很多农村家