This commit is contained in:
John 2018-08-23 21:55:27 +08:00
parent 569be7e773
commit 6f403d48c2
26 changed files with 155 additions and 66 deletions

5
TODO
View File

@ -21,6 +21,11 @@ ghttp路由功能增加分组路由特性
解决glog串日志情况
ghttp增加返回数据压缩机制
*any模糊匹配路由改进支持不带名字的*路由规则;
检查windows下的平滑重启失效问题
gview中的template标签失效问题
ghttp静态文件服务改进(特别是403返回状态的修改)
DONE:
1. gconv完善针对不同类型的判断例如尽量减少sprintf("%v", xxx)来执行string类型的转换

View File

@ -148,7 +148,7 @@ func (this *IntBoolMap) Size() int {
// 哈希表是否为空
func (this *IntBoolMap) IsEmpty() bool {
this.mu.RLock()
empty := (len(this.m) == 0)
empty := len(this.m) == 0
this.mu.RUnlock()
return empty
}
@ -163,13 +163,13 @@ func (this *IntBoolMap) Clear() {
// 使用自定义方法执行加锁修改操作
func (this *IntBoolMap) LockFunc(f func(m map[int]bool)) {
this.mu.Lock()
defer this.mu.Unlock()
f(this.m)
this.mu.Unlock()
}
// 使用自定义方法执行加锁读取操作
func (this *IntBoolMap) RLockFunc(f func(m map[int]bool)) {
this.mu.RLock()
defer this.mu.RUnlock()
f(this.m)
this.mu.RUnlock()
}

View File

@ -163,13 +163,13 @@ func (this *IntIntMap) Clear() {
// 使用自定义方法执行加锁修改操作
func (this *IntIntMap) LockFunc(f func(m map[int]int)) {
this.mu.Lock()
defer this.mu.Unlock()
f(this.m)
this.mu.Unlock()
}
// 使用自定义方法执行加锁读取操作
func (this *IntIntMap) RLockFunc(f func(m map[int]int)) {
this.mu.RLock()
defer this.mu.RUnlock()
f(this.m)
this.mu.RUnlock()
}

View File

@ -148,7 +148,7 @@ func (this *IntInterfaceMap) Size() int {
// 哈希表是否为空
func (this *IntInterfaceMap) IsEmpty() bool {
this.mu.RLock()
empty := (len(this.m) == 0)
empty := len(this.m) == 0
this.mu.RUnlock()
return empty
}
@ -163,13 +163,13 @@ func (this *IntInterfaceMap) Clear() {
// 使用自定义方法执行加锁修改操作
func (this *IntInterfaceMap) LockFunc(f func(m map[int]interface{})) {
this.mu.Lock()
defer this.mu.Unlock()
f(this.m)
this.mu.Unlock()
}
// 使用自定义方法执行加锁读取操作
func (this *IntInterfaceMap) RLockFunc(f func(m map[int]interface{})) {
this.mu.RLock()
defer this.mu.RUnlock()
f(this.m)
this.mu.RUnlock()
}

View File

@ -148,7 +148,7 @@ func (this *IntStringMap) Size() int {
// 哈希表是否为空
func (this *IntStringMap) IsEmpty() bool {
this.mu.RLock()
empty := (len(this.m) == 0)
empty := len(this.m) == 0
this.mu.RUnlock()
return empty
}
@ -170,6 +170,6 @@ func (this *IntStringMap) LockFunc(f func(m map[int]string)) {
// 使用自定义方法执行加锁读取操作
func (this *IntStringMap) RLockFunc(f func(m map[int]string)) {
this.mu.RLock()
defer this.mu.RUnlock()
f(this.m)
this.mu.RUnlock()
}

View File

@ -148,7 +148,7 @@ func (this *InterfaceInterfaceMap) Size() int {
// 哈希表是否为空
func (this *InterfaceInterfaceMap) IsEmpty() bool {
this.mu.RLock()
empty := (len(this.m) == 0)
empty := len(this.m) == 0
this.mu.RUnlock()
return empty
}
@ -163,13 +163,13 @@ func (this *InterfaceInterfaceMap) Clear() {
// 使用自定义方法执行加锁修改操作
func (this *InterfaceInterfaceMap) LockFunc(f func(m map[interface{}]interface{})) {
this.mu.Lock()
defer this.mu.Unlock()
f(this.m)
this.mu.Unlock()
}
// 使用自定义方法执行加锁读取操作
func (this *InterfaceInterfaceMap) RLockFunc(f func(m map[interface{}]interface{})) {
this.mu.RLock()
defer this.mu.RUnlock()
f(this.m)
this.mu.RUnlock()
}

View File

@ -148,7 +148,7 @@ func (this *StringBoolMap) Size() int {
// 哈希表是否为空
func (this *StringBoolMap) IsEmpty() bool {
this.mu.RLock()
empty := (len(this.m) == 0)
empty := len(this.m) == 0
this.mu.RUnlock()
return empty
}
@ -163,13 +163,13 @@ func (this *StringBoolMap) Clear() {
// 使用自定义方法执行加锁修改操作
func (this *StringBoolMap) LockFunc(f func(m map[string]bool)) {
this.mu.Lock()
defer this.mu.Unlock()
f(this.m)
this.mu.Unlock()
}
// 使用自定义方法执行加锁读取操作
func (this *StringBoolMap) RLockFunc(f func(m map[string]bool)) {
this.mu.RLock()
defer this.mu.RUnlock()
f(this.m)
this.mu.RUnlock()
}

View File

@ -148,7 +148,7 @@ func (this *StringIntMap) Size() int {
// 哈希表是否为空
func (this *StringIntMap) IsEmpty() bool {
this.mu.RLock()
empty := (len(this.m) == 0)
empty := len(this.m) == 0
this.mu.RUnlock()
return empty
}
@ -163,13 +163,13 @@ func (this *StringIntMap) Clear() {
// 使用自定义方法执行加锁修改操作
func (this *StringIntMap) LockFunc(f func(m map[string]int)) {
this.mu.Lock()
defer this.mu.Unlock()
f(this.m)
this.mu.Unlock()
}
// 使用自定义方法执行加锁读取操作
func (this *StringIntMap) RLockFunc(f func(m map[string]int)) {
this.mu.RLock()
defer this.mu.RUnlock()
f(this.m)
this.mu.RUnlock()
}

View File

@ -148,7 +148,7 @@ func (this *StringInterfaceMap) Size() int {
// 哈希表是否为空
func (this *StringInterfaceMap) IsEmpty() bool {
this.mu.RLock()
empty := (len(this.m) == 0)
empty := len(this.m) == 0
this.mu.RUnlock()
return empty
}
@ -163,13 +163,13 @@ func (this *StringInterfaceMap) Clear() {
// 使用自定义方法执行加锁修改操作
func (this *StringInterfaceMap) LockFunc(f func(m map[string]interface{})) {
this.mu.Lock()
defer this.mu.Unlock()
f(this.m)
this.mu.Unlock()
}
// 使用自定义方法执行加锁读取操作
func (this *StringInterfaceMap) RLockFunc(f func(m map[string]interface{})) {
this.mu.RLock()
defer this.mu.RUnlock()
f(this.m)
this.mu.RUnlock()
}

View File

@ -148,7 +148,7 @@ func (this *StringStringMap) Size() int {
// 哈希表是否为空
func (this *StringStringMap) IsEmpty() bool {
this.mu.RLock()
empty := (len(this.m) == 0)
empty := len(this.m) == 0
this.mu.RUnlock()
return empty
}
@ -163,13 +163,13 @@ func (this *StringStringMap) Clear() {
// 使用自定义方法执行加锁修改操作
func (this *StringStringMap) LockFunc(f func(m map[string]string)) {
this.mu.Lock()
defer this.mu.Unlock()
f(this.m)
this.mu.Unlock()
}
// 使用自定义方法执行加锁读取操作
func (this *StringStringMap) RLockFunc(f func(m map[string]string)) {
this.mu.RLock()
defer this.mu.RUnlock()
f(this.m)
this.mu.RUnlock()
}

View File

@ -147,7 +147,7 @@ func (this *UintInterfaceMap) Size() int {
// 哈希表是否为空
func (this *UintInterfaceMap) IsEmpty() bool {
this.mu.RLock()
empty := (len(this.m) == 0)
empty := len(this.m) == 0
this.mu.RUnlock()
return empty
}
@ -162,13 +162,13 @@ func (this *UintInterfaceMap) Clear() {
// 使用自定义方法执行加锁修改操作
func (this *UintInterfaceMap) LockFunc(f func(m map[uint]interface{})) {
this.mu.Lock()
defer this.mu.Unlock()
f(this.m)
this.mu.Unlock()
}
// 使用自定义方法执行加锁读取操作
func (this *UintInterfaceMap) RLockFunc(f func(m map[uint]interface{})) {
this.mu.RLock()
defer this.mu.RUnlock()
f(this.m)
this.mu.RUnlock()
}

View File

@ -5,7 +5,7 @@
// You can obtain one at https://gitee.com/johng/gf.
// 并发安全的动态队列.
// 点:
// 点:
// 1、队列初始化速度快
// 2、可以向队头/队尾进行Push/Pop操作
// 3、取数据时如果队列为空那么会阻塞等待

View File

@ -53,6 +53,8 @@ func View() *gview.View {
if p := gfile.MainPkgPath(); gfile.Exists(p) {
view.AddPath(p)
}
// 框架内置函数
view.BindFunc("config", funcConfig)
Set(gFRAME_CORE_COMPONENT_NAME_VIEW, view)
return view
}
@ -84,3 +86,9 @@ func Config() *gcfg.Config {
}
return nil
}
// 模板内置方法config
func funcConfig(pattern string, file...string) gview.HTML {
return gview.HTML(Config().GetString(pattern, file...))
}

View File

@ -17,7 +17,8 @@ import (
type View struct {
mu sync.RWMutex // 并发互斥锁
view *gview.View // 底层视图对象
data map[string]interface{} // 视图数据/模板变量
data gview.Params // 视图数据/模板变量
fmap gview.FuncMap // 绑定的模板函数
response *ghttp.Response // 数据返回对象
}
@ -25,13 +26,14 @@ type View struct {
func NewView(w *ghttp.Response) *View {
return &View {
view : gins.View(),
data : make(map[string]interface{}),
data : make(gview.Params),
fmap : make(gview.FuncMap),
response : w,
}
}
// 批量绑定模板变量,即调用之后每个线程都会生效,因此有并发安全控制
func (view *View) Assigns(data map[string]interface{}) {
func (view *View) Assigns(data gview.Params) {
view.mu.Lock()
for k, v := range data {
view.data[k] = v
@ -46,34 +48,41 @@ func (view *View) Assign(key string, value interface{}) {
view.mu.Unlock()
}
// 绑定自定义模板函数
func (view *View) BindFunc(name string, function interface{}){
view.mu.Lock()
view.fmap[name] = function
view.mu.Unlock()
}
// 解析模板,并返回解析后的内容
func (view *View) Parse(file string) ([]byte, error) {
view.mu.RLock()
buffer, err := view.view.Parse(file, view.data)
view.mu.RUnlock()
defer view.mu.RUnlock()
buffer, err := view.view.Parse(file, view.data, view.fmap)
return buffer, err
}
// 直接解析模板内容,并返回解析后的内容
func (view *View) ParseContent(content string) ([]byte, error) {
view.mu.RLock()
buffer, err := view.view.ParseContent(content, view.data)
view.mu.RUnlock()
defer view.mu.RUnlock()
buffer, err := view.view.ParseContent(content, view.data, view.fmap)
return buffer, err
}
// 使用自定义方法对模板变量执行加锁修改操作
func (view *View) LockFunc(f func(vars map[string]interface{})) {
func (view *View) LockFunc(f func(data gview.Params)) {
view.mu.Lock()
defer view.mu.Unlock()
f(view.data)
view.mu.Unlock()
}
// 使用自定义方法对模板变量执行加锁读取操作
func (view *View) RLockFunc(f func(vars map[string]interface{})) {
func (view *View) RLockFunc(f func(data gview.Params)) {
view.mu.RLock()
defer view.mu.RUnlock()
f(view.data)
view.mu.RUnlock()
}
// 解析并显示指定模板

View File

@ -13,7 +13,6 @@ import (
"gitee.com/johng/gf/g/encoding/gparser"
"strconv"
"fmt"
"gitee.com/johng/gf/g/frame/gins"
)
// 服务端请求返回对象。
@ -119,15 +118,6 @@ func (r *Response) WriteXml(content interface{}, rootTag...string) error {
return nil
}
func (r *Response) Template(tpl string, params...map[string]interface{}) error {
if b, err := gins.View().Parse(tpl, params...); err != nil {
return err
} else {
r.Write(b)
}
return nil
}
// 允许AJAX跨域访问
func (r *Response) SetAllowCrossDomainRequest(allowOrigin string, allowMethods string, maxAge...int) {
age := 3628800

View File

@ -0,0 +1,47 @@
// Copyright 2017 gf Author(https://gitee.com/johng/gf). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://gitee.com/johng/gf.
//
package ghttp
import (
"gitee.com/johng/gf/g/os/gview"
"gitee.com/johng/gf/g/frame/gins"
)
// 展示模板,可以给定模板参数,及临时的自定义模板函数
func (r *Response) Template(tpl string, params map[string]interface{}, funcmap...map[string]interface{}) error {
fmap := make(gview.FuncMap)
if len(funcmap) > 0 {
fmap = funcmap[0]
}
// 内置函数
fmap["get"] = r.funcGet
fmap["post"] = r.funcPost
fmap["request"] = r.funcRequest
if b, err := gins.View().Parse(tpl, params, fmap); err != nil {
r.Write("Tpl Parsing Error: " + err.Error())
return err
} else {
r.Write(b)
}
return nil
}
// 模板内置函数: get
func (r *Response) funcGet(key string, def...string) gview.HTML {
return gview.HTML(r.request.GetQueryString(key, def...))
}
// 模板内置函数: post
func (r *Response) funcPost(key string, def...string) gview.HTML {
return gview.HTML(r.request.GetPostString(key, def...))
}
// 模板内置函数: request
func (r *Response) funcRequest(key string, def...string) gview.HTML {
return gview.HTML(r.request.Get(key, def...))
}

View File

@ -27,17 +27,21 @@ type View struct {
delimiters []string // 模板变量分隔符号
}
// 输出到模板页面时保留HTML标签原意不做自动escape处理
type HTML = template.HTML
// 模板变量
type Params = map[string]interface{}
// 函数映射表
type FuncMap = map[string]interface{}
// 视图表
var viewMap = gmap.NewStringInterfaceMap()
// 默认的视图对象
var viewObj = Get(".")
// 输出到模板页面时保留HTML标签原意不做自动escape处理
func HTML(content string) template.HTML {
return template.HTML(content)
}
// 直接解析模板内容,返回解析后的内容
func ParseContent(content string, params map[string]interface{}) ([]byte, error) {
return viewObj.ParseContent(content, params)
@ -63,6 +67,7 @@ func New(path string) *View {
delimiters : make([]string, 2),
}
view.SetDelimiters("{{", "}}")
// 内置方法
view.BindFunc("include", view.funcInclude)
return view
}
@ -78,26 +83,24 @@ func (view *View) AddPath(path string) error {
}
// 解析模板,返回解析后的内容
func (view *View) Parse(file string, params...map[string]interface{}) ([]byte, error) {
func (view *View) Parse(file string, params map[string]interface{}, funcmap...map[string]interface{}) ([]byte, error) {
path := view.paths.Search(file)
if path == "" {
return nil, errors.New("tpl \"" + file + "\" not found")
}
content := gfcache.GetContents(path)
// 模板参数
data := (map[string]interface{})(nil)
if len(params) > 0 {
data = params[0]
}
// 执行模板解析互斥锁主要是用于funcmap
view.mu.RLock()
defer view.mu.RUnlock()
buffer := bytes.NewBuffer(nil)
if tpl, err := template.New(path).Delims(view.delimiters[0], view.delimiters[1]).Funcs(view.funcmap).Parse(content); err != nil {
tplobj := template.New(path).Delims(view.delimiters[0], view.delimiters[1]).Funcs(view.funcmap)
if len(funcmap) > 0 {
tplobj = tplobj.Funcs(funcmap[0])
}
if tpl, err := tplobj.Parse(content); err != nil {
return nil, err
} else {
if err := tpl.Execute(buffer, data); err != nil {
if err := tpl.Execute(buffer, params); err != nil {
return nil, err
}
}
@ -105,12 +108,16 @@ func (view *View) Parse(file string, params...map[string]interface{}) ([]byte, e
}
// 直接解析模板内容,返回解析后的内容
func (view *View) ParseContent(content string, params map[string]interface{}) ([]byte, error) {
func (view *View) ParseContent(content string, params map[string]interface{}, funcmap...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).Delims(view.delimiters[0], view.delimiters[1]).Funcs(view.funcmap).Parse(content); err != nil {
tplobj := template.New(name).Delims(view.delimiters[0], view.delimiters[1]).Funcs(view.funcmap)
if len(funcmap) > 0 {
tplobj = tplobj.Funcs(funcmap[0])
}
if tpl, err := tplobj.Parse(content); err != nil {
return nil, err
} else {
if err := tpl.Execute(buffer, params); err != nil {

View File

@ -0,0 +1,22 @@
package main
import (
"fmt"
"gitee.com/johng/gf/g"
"gitee.com/johng/gf/g/os/gview"
)
// 用于测试的内置函数
func funcTest() string {
return "test"
}
func main() {
view := g.View()
b, err := view.Parse("gview.tpl", nil, gview.FuncMap{
"test" : funcTest,
})
fmt.Println(err)
fmt.Println(string(b))
}

View File

@ -0,0 +1 @@
{{test}}