mirror of
https://gitee.com/johng/gf
synced 2026-06-07 10:22:11 +08:00
Merge branch 'master' of http://johnx.cn:6662/John/gf into qiangg_gfsnotify
This commit is contained in:
@ -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 {
|
||||
|
||||
@ -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)),
|
||||
@ -148,7 +149,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 +208,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,
|
||||
|
||||
@ -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())
|
||||
}
|
||||
|
||||
@ -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")
|
||||
}
|
||||
|
||||
|
||||
@ -33,6 +33,9 @@ func (c *ControllerUser) Age() {
|
||||
|
||||
// 定义操作逻辑 - 展示方法名称如果带多个单词,路由控制器使用英文连接符号"-"进行拼接
|
||||
func (c *ControllerUser) TrueName() {
|
||||
c.View.Assigns(map[string]interface{}{
|
||||
|
||||
})
|
||||
c.Response.Write("John Smith")
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user