golang微服務架構go-zero系列-4:go-zero檔案服務
go-zero本身支援檔案服務,但是我們需要寫相關的handler檔案,本文目的在于
- 不寫任何一個和檔案相關的handler
- 如果有新的檔案,直接把檔案模闆到某個特定目錄就好,不要動任何go代碼
需求在這裡,開撸吧
在代碼開始前,你可能需要閱讀
golang微服務架構go-zero系列-1:在go-zero中使用XormV2
golang微服務架構go-zero系列-2:在go-zero中使用jwt-token鑒權實踐
golang微服務架構go-zero系列-3:擴充go-zero,使之支援html模闆解析自動化
注意
微服務講究資源分離,實際生産過程中盡量使用專業的檔案伺服器或者OSS等第三方存儲平台
file服務實作思路
在
gin
中有專門的
static file
服務封裝,
go-zero
目前并沒有提供。目前
go-zero
提供非常嚴格的路徑比對,如
通路
/asset/l1.jpg
将映射到
/asset/:1
對應的handlerlv1
/asset/l1/l2.jpg
将映射到
/asset/:1/:2
對應的handlerlv2
這有如下倆種情況
映射指定路徑到單個檔案
比如我們需要通路
favourite.ico
,系統指向
./www/favourite.ico
檔案,代碼如下
//處理函數,傳入檔案位址
func filehandler(filepath string) http.HandlerFunc {
return func(w http.ResponseWriter, req *http.Request) {
http.ServeFile(w, req, filepath)
}
}
在router裡面直接調用
AddRoute
方法添加單個路由
func RegisterHandlers(engine *rest.Server, serverCtx *svc.ServiceContext) {
//這裡直接添加單個
engine.AddRoute(
rest.Route{
Method: http.MethodGet,
Path: "/favourite.ico",
Handler: filehandler("./www/favourite.ico"),
})
}
映射指定目錄并提供服務
實際過程中我們需要對外暴露某一個目錄,比如
/assets/
目錄,該目錄下存放一些資源檔案如
css
,
js
,
img
等
tree /f
+---assets
| +---css
| +---fonts
| +---images
| +---js
| \---plugins
| +---font-awesome
| | +---css
| | \---fonts
| +---fontawesome
| | +---css
| | \---fonts
| +---ionicons
| | +---css
| | \---fonts
| +---jquery.contextmenu
| | \---images
| +---jquery.pin
| | +---css
| | \---images
| +---jqueryui-1.12.1
| | +---external
| | | \---jquery
| | \---images
| \---swiper-4.5.3
| +---css
| \---js
如果使用單個檔案的方式來實作,肯定不合理,因為router會非常大,怎麼解決這個問題?我們可以使用如下方法實作檔案夾服務
//
func dirhandler(patern, filedir string) http.HandlerFunc {
return func(w http.ResponseWriter, req *http.Request) {
handler := http.StripPrefix(patern, http.FileServer(http.Dir(filedir)))
handler.ServeHTTP(w, req)
}
}
如上函數的核心是
http.StripPrefix(patern, http.FileServer(http.Dir(filedir)))
函數,這個函數的核心功能是将映
patern
格式映射到某一個目錄
filedir
- patern:請求路徑格式
,/assets/:1
這種/assets/:1/:2
- filedir:映射對應的檔案夾
這種./assets/
那麼我們隻需要建構多級檔案通路格式和
dirhandler
的映射關系即可
func RegisterHandlers(engine *rest.Server, serverCtx *svc.ServiceContext) {
//這裡注冊
dirlevel := []string{":1", ":2", ":3", ":4", ":5", ":6", ":7", ":8"}
patern := "/asset/"
dirpath := "./assets/"
for i := 1; i < len(dirlevel); i++ {
path := prefix + strings.Join(dirlevel[:i], "/")
//最後生成 /asset
engine.AddRoute(
rest.Route{
Method: http.MethodGet,
Path: path,
Handler: dirhandler(patern,dirpath),
})
logx.Infof("register dir %s %s", path,dirpath)
}
}
404
404可以在main函數中配置
rt := router.NewPatRouter()
rt.SetNotFoundHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
//這裡内容可以定制
w.Write([]byte("伺服器開小差了,這裡可定制"))
}))
server := rest.MustNewServer(c.RestConf, rest.WithRouter(rt))
此時請求
http://127.0.0.1:8888/hello
,系統響應
伺服器開小差了,這裡可定制
測試
啟動系統後運作
E:\[email protected]\gozero\file>go run file.go
2020/09/05 20:18:24 {"@timestamp":"2020-09-05T20:18:24.682+08","level":"info","content":"{{{file-api { console logs info false 0 100} pro { 0 }} 0.0.0.0 8081 false 10000 1048576 3000 900 {false 0s []}} [/asset/=./assets]}"}
{"@timestamp":"2020-09-05T20:18:24.682+08","level":"info","content":"register dir /asset/:1 ./assets"}
{"@timestamp":"2020-09-05T20:18:24.683+08","level":"info","content":"register dir /asset/:1/:2 ./assets"}
{"@timestamp":"2020-09-05T20:18:24.683+08","level":"info","content":"register dir /asset/:1/:2/:3 ./assets"}
{"@timestamp":"2020-09-05T20:18:24.683+08","level":"info","content":"register dir /asset/:1/:2/:3/:4 ./assets"}
{"@timestamp":"2020-09-05T20:18:24.697+08","level":"info","content":"register dir /asset/:1/:2/:3/:4/:5 ./assets"}
{"@timestamp":"2020-09-05T20:18:24.697+08","level":"info","content":"register dir /asset/:1/:2/:3/:4/:5/:6 ./assets"}
{"@timestamp":"2020-09-05T20:18:24.698+08","level":"info","content":"register dir /asset/:1/:2/:3/:4/:5/:6/:7 ./assets"}
通路系統都能正常響應
http://127.0.0.1:8888/asset/images/avatar.jpg
http://127.0.0.1:8888/asset/js/test.js
http://127.0.0.1:8888/asset/js/lv2/test.js
注意,請求的是不是
/asset/**
/assets/**
思考一下
我們可以在NotFoundHandler中根據req.URL.path來實作檔案服務,如何實作呢?
下章預告
單體應用需要的基本梳理完,明天開始微服務
本文代碼擷取
關注公衆号
betaidea
輸入
file
即可獲得本文相關代碼
關注公衆号
betaidea
輸入
html
即可獲得html解析相關代碼
關注公衆号
betaidea
輸入
jwt
即可獲得gozero內建jwt-token相關代碼
關注公衆号
betaidea
輸入
gozero
即可gozero入門代碼
廣而告之
送福利了uniapp使用者福音來啦!
曆經數十萬使用者考驗,我們的客服系統終于對外提供服務了。
你還在為商城接入客服煩惱嗎?隻需一行代碼,即可接入啦!!
隻需一行代碼!!!
/*kefu.vue*/
<template>
<view>
<IdeaKefu :siteid="siteId" ></IdeaKefu>
</view>
</template>
<script>
import IdeaKefu from "@/components/idea-kefu/idea-kefu.vue"
export default {
components:{
IdeaKefu
},
data() {
return {
siteId:2
}
}
}
效果杠杠的
開發文檔位址
http://kefu.techidea8.com/html/wiki/