From c556594488bb7829d778855bbc9ba334b73f5e66 Mon Sep 17 00:00:00 2001 From: John Date: Wed, 18 Apr 2018 10:15:07 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=A8=A1=E6=9D=BF=E5=BC=95=E6=93=8E?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=8F=98=E9=87=8F=E6=9A=B4=E9=9C=B2=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=EF=BC=8C=E4=BF=AE=E6=AD=A3ghttp=20RESTful=E6=B3=A8?= =?UTF-8?q?=E5=86=8C=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/frame/gmvc/view.go | 34 +++++++++++++++++++-------- g/net/ghttp/http_server_service.go | 16 ++++--------- g/os/gview/gview.go | 32 ++++++++++--------------- geg/frame/mvc/controller/demo/rest.go | 10 ++++---- geg/frame/mvc/controller/demo/user.go | 3 +++ 5 files changed, 49 insertions(+), 46 deletions(-) diff --git a/g/frame/gmvc/view.go b/g/frame/gmvc/view.go index 6192e73d4..09c3ee321 100644 --- a/g/frame/gmvc/view.go +++ b/g/frame/gmvc/view.go @@ -13,17 +13,17 @@ import ( "gitee.com/johng/gf/g/frame/gins" ) -// MVC视图基类(一个请求一个视图对象,用完即销毁) +// 基于控制器注册的MVC视图基类(一个请求一个视图对象,用完即销毁) type View struct { mu sync.RWMutex // 并发互斥锁 view *gview.View // 底层视图对象 - data map[string]interface{} // 视图数据 + data map[string]interface{} // 视图数据/模板变量 response *ghttp.Response // 数据返回对象 } // 创建一个MVC请求中使用的视图对象 func NewView(w *ghttp.Response) *View { - return &View{ + return &View { view : gins.View(), data : make(map[string]interface{}), response : w, @@ -33,17 +33,17 @@ func NewView(w *ghttp.Response) *View { // 批量绑定模板变量,即调用之后每个线程都会生效,因此有并发安全控制 func (view *View) Assigns(data map[string]interface{}) { view.mu.Lock() - defer view.mu.Unlock() for k, v := range data { view.data[k] = v } + view.mu.Unlock() } // 绑定模板变量,即调用之后每个线程都会生效,因此有并发安全控制 func (view *View) Assign(key string, value interface{}) { view.mu.Lock() - defer view.mu.Unlock() view.data[key] = value + view.mu.Unlock() } // 解析模板,并返回解析后的内容 @@ -62,13 +62,27 @@ func (view *View) ParseContent(content string) ([]byte, error) { return buffer, err } +// 使用自定义方法对模板变量执行加锁修改操作 +func (view *View) LockFunc(f func(vars map[string]interface{})) { + view.mu.Lock() + f(view.data) + view.mu.Unlock() +} + +// 使用自定义方法对模板变量执行加锁读取操作 +func (view *View) RLockFunc(f func(vars map[string]interface{})) { + view.mu.RLock() + f(view.data) + view.mu.RUnlock() +} + // 解析指定模板 -func (view *View) Display(files...string) error { - file := "index.tpl" - if len(files) > 0 { - file = files[0] +func (view *View) Display(file...string) error { + name := "index.tpl" + if len(file) > 0 { + name = file[0] } - if content, err := view.Parse(file); err != nil { + if content, err := view.Parse(name); err != nil { view.response.Write("Tpl Parsing Error: " + err.Error()) return err } else { diff --git a/g/net/ghttp/http_server_service.go b/g/net/ghttp/http_server_service.go index 5772282fd..8e1b8910e 100644 --- a/g/net/ghttp/http_server_service.go +++ b/g/net/ghttp/http_server_service.go @@ -148,7 +148,7 @@ func (s *Server)BindController(pattern string, c Controller) error { t := v.Type() for i := 0; i < v.NumMethod(); i++ { name := t.Method(i).Name - if name == "Init" || name == "Shut" { + if name == "Init" || name == "Shut" || name == "Exit" { continue } key := s.appendMethodNameToUriWithPattern(pattern, name) @@ -207,21 +207,15 @@ func (s *Server)BindControllerRest(pattern string, c Controller) error { m := make(HandlerMap) v := reflect.ValueOf(c) t := v.Type() - methods := make(map[string]bool) - for _, v := range strings.Split(gHTTP_METHODS, ",") { - methods[v] = true - } // 如果存在与HttpMethod对应名字的方法,那么绑定这些方法 for i := 0; i < v.NumMethod(); i++ { - name := strings.ToUpper(t.Method(i).Name) - if name == "Init" || name == "Shut" { - continue - } - if _, ok := s.methodsMap[name]; !ok { + name := t.Method(i).Name + method := strings.ToUpper(name) + if _, ok := s.methodsMap[method]; !ok { continue } key := name + ":" + pattern - m[key] = &HandlerItem{ + m[key] = &HandlerItem { ctype : v.Elem().Type(), fname : name, faddr : nil, diff --git a/g/os/gview/gview.go b/g/os/gview/gview.go index 12c877e42..ee0254992 100644 --- a/g/os/gview/gview.go +++ b/g/os/gview/gview.go @@ -64,7 +64,8 @@ func (view *View) GetPath() string { // 解析模板,返回解析后的内容 func (view *View) Parse(file string, params map[string]interface{}) ([]byte, error) { - // 获取模板文件路径及内容 + view.mu.RLock() + defer view.mu.RUnlock() path := strings.TrimRight(view.GetPath(), gfile.Separator) + gfile.Separator + file content := view.contents.Get(path) if content == "" { @@ -79,7 +80,7 @@ func (view *View) Parse(file string, params map[string]interface{}) ([]byte, err } // 执行模板解析 buffer := bytes.NewBuffer(nil) - if tpl, err := template.New(path).Funcs(view.getFuncs()).Parse(content); err != nil { + if tpl, err := template.New(path).Funcs(view.funcmap).Parse(content); err != nil { return nil, err } else { if err := tpl.Execute(buffer, params); err != nil { @@ -91,9 +92,11 @@ func (view *View) Parse(file string, params map[string]interface{}) ([]byte, err // 直接解析模板内容,返回解析后的内容 func (view *View) ParseContent(content string, params map[string]interface{}) ([]byte, error) { + view.mu.RLock() + defer view.mu.RUnlock() name := gconv.String(ghash.BKDRHash64([]byte(content))) buffer := bytes.NewBuffer(nil) - if tpl, err := template.New(name).Funcs(view.getFuncs()).Parse(content); err != nil { + if tpl, err := template.New(name).Funcs(view.funcmap).Parse(content); err != nil { return nil, err } else { if err := tpl.Execute(buffer, params); err != nil { @@ -106,28 +109,17 @@ func (view *View) ParseContent(content string, params map[string]interface{}) ([ // 绑定自定义函数,该函数是全局有效,即调用之后每个线程都会生效,因此有并发安全控制 func (view *View) BindFunc(name string, function interface{}) { view.mu.Lock() - defer view.mu.Unlock() view.funcmap[name] = function -} - -// 获取模板自定义函数,每一次都是一份拷贝 -func (view *View) getFuncs() map[string]interface{} { - m := make(map[string]interface{}) - view.mu.RLock() - for k, v := range view.funcmap { - m[k] = v - } - view.mu.RUnlock() - return m + view.mu.Unlock() } // 模板内置方法:include -func (view *View) funcInclude(file string, datas...map[string]interface{}) template.HTML { - var data map[string]interface{} = nil - if len(datas) > 0 { - data = datas[0] +func (view *View) funcInclude(file string, data...map[string]interface{}) template.HTML { + var m map[string]interface{} = nil + if len(data) > 0 { + m = data[0] } - content, err := view.Parse(file, data) + content, err := view.Parse(file, m) if err != nil { return template.HTML(err.Error()) } diff --git a/geg/frame/mvc/controller/demo/rest.go b/geg/frame/mvc/controller/demo/rest.go index ba04a1927..12de58d7b 100644 --- a/geg/frame/mvc/controller/demo/rest.go +++ b/geg/frame/mvc/controller/demo/rest.go @@ -13,26 +13,26 @@ type ControllerRest struct { // 初始化控制器对象,并绑定操作到Web Server func init() { // 控制器公开方法中与HTTP Method方法同名的方法将会自动绑定映射 - ghttp.GetServer().BindControllerRest("/user", &ControllerRest{}) + ghttp.GetServer().BindControllerRest("/john", &ControllerRest{}) } // RESTFul - GET -func (c *ControllerUser) Get() { +func (c *ControllerRest) Get() { c.Response.Write("RESTFul HTTP Method GET") } // RESTFul - POST -func (c *ControllerUser) Post() { +func (c *ControllerRest) Post() { c.Response.Write("RESTFul HTTP Method POST") } // RESTFul - DELETE -func (c *ControllerUser) Delete() { +func (c *ControllerRest) Delete() { c.Response.Write("RESTFul HTTP Method DELETE") } // 该方法无法映射,将会无法访问到 -func (c *ControllerUser) Hello() { +func (c *ControllerRest) Hello() { c.Response.Write("Hello") } diff --git a/geg/frame/mvc/controller/demo/user.go b/geg/frame/mvc/controller/demo/user.go index 31502096f..82d2b00a1 100644 --- a/geg/frame/mvc/controller/demo/user.go +++ b/geg/frame/mvc/controller/demo/user.go @@ -33,6 +33,9 @@ func (c *ControllerUser) Age() { // 定义操作逻辑 - 展示方法名称如果带多个单词,路由控制器使用英文连接符号"-"进行拼接 func (c *ControllerUser) TrueName() { + c.View.Assigns(map[string]interface{}{ + + }) c.Response.Write("John Smith") } From 6850e3a4b0d74aac9ebae29f7830107996cb0d32 Mon Sep 17 00:00:00 2001 From: John Date: Wed, 18 Apr 2018 10:17:05 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E5=AE=8C=E5=96=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- g/net/ghttp/http_server_service.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/g/net/ghttp/http_server_service.go b/g/net/ghttp/http_server_service.go index 8e1b8910e..909fc9d27 100644 --- a/g/net/ghttp/http_server_service.go +++ b/g/net/ghttp/http_server_service.go @@ -125,12 +125,13 @@ func (s *Server)BindObjectRest(pattern string, obj interface{}) error { v := reflect.ValueOf(obj) t := v.Type() for i := 0; i < v.NumMethod(); i++ { - name := t.Method(i).Name - if _, ok := s.methodsMap[strings.ToUpper(name)]; !ok { + name := t.Method(i).Name + method := strings.ToUpper(name) + if _, ok := s.methodsMap[method]; !ok { continue } key := name + ":" + pattern - m[key] = &HandlerItem{ + m[key] = &HandlerItem { ctype : nil, fname : "", faddr : v.Method(i).Interface().(func(*Request)),