天天看點

golang微服務架構go-zero系列-4:go-zero檔案服務golang微服務架構go-zero系列-4:go-zero檔案服務在代碼開始前,你可能需要閱讀注意file服務實作思路下章預告本文代碼擷取廣而告之

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
			}
		}
    }   
           

效果杠杠的

golang微服務架構go-zero系列-4:go-zero檔案服務golang微服務架構go-zero系列-4:go-zero檔案服務在代碼開始前,你可能需要閱讀注意file服務實作思路下章預告本文代碼擷取廣而告之

開發文檔位址

http://kefu.techidea8.com/html/wiki/