Go语言Web框架gwk介绍4
Go语言Web框架gwk介绍 (四)
事件
gwk支持事件系统,但并没有硬编码有哪些事件,而是采用了比较松散的定义方式。
订阅事件有两种方式: 调用On函数或者OnFunc函数
func On(moudle, name string, handler Subscriber)
func OnFunc(moudle, name string, handler func(*EventContext))
参数moudle是指订阅哪一个模块触发的事件,参数name是指订阅事件的名字,参数handler是处理事件的对象实例,是Subscriber类型的对象,Subscriber接口定义如下:
type Subscriber interface {
On(e *EventContext)
}
type SubscriberFunc func(*EventContext)
func (f SubscriberFunc) On(e *EventContext) {
f(e)
}
EventContext定义如下:
type EventContext struct {
Moudle string
Name string
Source interface{}
Data interface{}
Context *HttpContext
}
- Moudle: 触发事件的模块名
- Name: 事件名
- Source: 触发事件的变量
- Data: 事件附带的参数,每个事件可能不同,由Source负责赋值
- Context: HttpContext
如果想要触发一个自定义事件,要调用HttpServer的Fire方法:
func (srv *HttpServer) Fire(moudle, name string, source, data interface{}, context *HttpContext)
参数说明参照EventContext的定义。
使用事件系统可以做权限验证,日志、同一错误处理等等,十分方便。
demo/basic项目中的event.go演示了如何使用事件:
wk.OnFunc("*", "*", eventTraceFunc)
这段代码调用OnFunc订阅了所有的事件,在eventTraceFunc中记录所有事件的触发时间并存在HttpContext的Flash字段中,在Server端结束所有处理前把这些数据返回客户端,这样客户端就能得到每个代码段的执行时间。返回的数据格式如下:
_webserver start_request 0 ns
_static start_execute 13761 ns
_static end_execute 24829 ns
_route start_execute 27988 ns
_route start_action 50774 ns
_route end_action 62984 ns
_route end_execute 64255 ns
_render start_execute 66379 ns
_render start_result 68203 ns
_render end_result 27631463 ns
_render end_execute 27634149 ns
_webserver end_request 27636472 ns
上面的数据列出了默认情况下gwk会触发的所有事件。
上面的例子给出了profile代码执行事件的一种思路。
配置
前面的例子都是基于gwk的默认配置,接下来将如何自定义配置以及如何使用gwk的配置框架。
gwk默认读取文件.conf/web.conf作为配置,如果文件不存在则采用预定义的默认配置。WebConfig的定义如下:
type WebConfig struct {
// 你可以给每一个Server设一个单独的名字,默认为""
ServerKey string
// 要监听的地址,默认为"0.0.0.0:8080"
Address string
// 根目录,默认为当前的工作目录
RootDir string
// 执行超时时间设置
Timeout int
// 静态文件的根目录,默认为RootDir下的public目录
PublicDir string
// 配置文件所在的目录,默认为RootDir下的conf目录
ConfigDir string
// View模板文件所在的目录,默认为RootDir下的views目录
ViewDir string
// 解析ConfigDir目录下的app.conf
AppConfig *kson.Node
// 解析ConfigDir目录下的plugin.conf
PluginConfig *kson.Node
// 读取Request的超时时间(秒)
ReadTimeout int
// 写Response的超时时间(秒)
WriteTimeout int
// Request headers的最大值
MaxHeaderBytes int
// 是否启用session
SessionEnable bool
// session的过期时间(秒)
SessionTimeout int
// SessionDriver is the name of driver
SessionDriver string
// 是否启用View引擎
ViewEnable bool
// 是否允许目录浏览,类似apache的Indexes
IndexesEnable bool
// 是否允许自定义404页面
NotFoundPageEnable bool
// 是否允许自定义错误页面
ErrorPageEnable bool
// 是否开启Debug模式
Debug bool
}
如果ConfigDir目录下存在app.conf和plugin.conf文件,gwk解析这两个文件并将解析好的内容存在AppConfig字段和PluginConfig字段,建议app.conf存放程序的配置数据,plugin.conf存放gwk各模块的配置数据。
如果app.conf文件存在,gwk会使用fsnotify监控这个文件,如果文件改动就重新解析并刷新AppConfig字段。
kson
gwk的配置文件采用自创的kson格式,类似json或者yaml,项目地址在https://github.com/sdming/kiss/tree/master/kson,详细的例子请看项目的readme.md
kson特点是
- 首先方便人类阅读
- 字符串不需要用"",除非存在特殊字符
- 不需要用","分割字段,默认回车就是分隔符
- 类似yaml但是不依赖缩进
- 支持普通类型、map、slice、struct的序列化和反序列化
- 支持注释,#开始的行会被看做注释,不会被解析
先看一个配置数据的例子
#app config file demo
#string
key_string: demo
#string
key_int: 101
#bool
key_bool: true
#float
key_float: 3.14
#map
key_map: {
key1: key1 value
key2: key2 value
}
#array
key_array: [
item 1
item 2
]
#struct
key_struct: {
Driver: mysql
Host: 127.0.0.1
User: user
Password: password
}
#composite
key_config: {
Log_Level: debug
Listen: 8000
Roles: [
{
Name: user
Allow: [
/user
/order
]
}
{
Name: *
Deny: [
/user
/order
]
}
]
Db_Log: {
Driver: mysql
Host: 127.0.0.1
User: user
Password: password
Database: log
}
Env: {
auth: http://auth.io
browser: ie, chrome, firefox, safari
}
}
对应的Go代码的定义
type Driver struct {
Driver string
Host string
User string
Password string
A string
B string
}
type Config struct {
Log_Level string
Listen uint
Roles []Role
Db_Log Db
Env map[string]string
}
type Role struct {
Name string
Allow []string
Deny []string
}
type Db struct {
Driver string
Host string
User string
Password string
}
kson格式的数据解析后存在kson.Node类型的实例中,具体的定义请参考kson项目的说明,这里只介绍kson.Node几个常用方法。
Dump
将node里的数据dump为kson格式的文本
func (c *ConfigController) Dump(ctx *wk.HttpContext) (wk.HttpResult, error) {
return wk.Data(c.node.MustChild("key_config").Dump()), nil
}
Child
根据name返回node的子节点
func (c *ConfigController) Child(ctx *wk.HttpContext) (wk.HttpResult, error) {
_, ok := c.node.Child("key_string")
return wk.Data(ok), nil
}
Query
查询node的子节点,现版本只支持按照节点名查询,以后可能支持按照属性查询比如 name[@field=xxx]
func (c *ConfigController) Query(ctx *wk.HttpContext) (wk.HttpResult, error) {
n, ok := c.node.Query("key_config Db_Log Host")
if ok {
return wk.Data(n.Literal), nil
}
return wk.Data(ok), nil
}
ChildStringOrDefault
将子节点的内容解析为字符串返回,如果子节点不存在则返回默认值,类似的方法还有ChildIntOrDefault, ChildUintOrDefault, ChildFloatOrDefault, ChildBoolOrDefault, ChildStringOrDefault等
func (c *ConfigController) ChildStringOrDefault(ctx *wk.HttpContext) (wk.HttpResult, error) {
s := c.node.ChildStringOrDefault("key_string_not", "default value")
return wk.Data(s), nil
}
ChildInt
将子节点的内容解析为Int64返回,如果子节点不存在则panic,类似的方法还有ChildInt, ChildUint, ChildFloat, ChildBool, ChildString等
func (c *ConfigController) ChildInt(ctx *wk.HttpContext) (wk.HttpResult, error) {
i := c.node.ChildInt("key_int")
return wk.Data(i), nil
}
Bool
将节点的值解析为bool返回,类似的方法还有Int, Uint, Float, Bool, String等
func (c *ConfigController) Bool(ctx *wk.HttpContext) (wk.HttpResult, error) {
b, err := c.node.MustChild("key_bool").Bool()
if err != nil {
return nil, err
}
return wk.Data(b), nil
}
Slice
将子节点的内容解析为[]string
func (c *ConfigController) Slice(ctx *wk.HttpContext) (wk.HttpResult, error) {
data, err := c.node.MustChild("key_array").Slice()
if err != nil {
return nil, err
}
return wk.Data(data), nil
}
Map
将子节点的内容解析为map[string]string
func (c *ConfigController) Map(ctx *wk.HttpContext) (wk.HttpResult, error) {
data, err := c.node.MustChild("key_map").Map()
if err != nil {
return nil, err
}
return wk.Data(data), nil
}
Value
将子节点的内容解析到一个interface{},传入的参数必须是可以通过reflect赋值的。
func (c *ConfigController) Value(ctx *wk.HttpContext) (wk.HttpResult, error) {
v := Driver{
Driver: "driver",
Host: "host",
User: "user",
Password: "password",
A: "aaa",
B: "bbb",
}
err := c.node.MustChild("key_struct").Value(&v)
if err != nil {
return nil, err
}
return wk.Data(v), nil
}
接下来是一个解析复杂格式的例子
func (c *ConfigController) Composite(ctx *wk.HttpContext) (wk.HttpResult, error) {
conf := &Config{}
err := c.node.MustChild("key_config").Value(conf)
if err != nil {
return nil, err
}
return wk.Data(conf), nil
}
kson支持常见数据格式(不承诺支持所有的数据格式),而且解析速度比json要快。
Go语言Web框架gwk介绍4的更多相关文章
- Go语言Web框架gwk介绍 3
Go语言Web框架gwk介绍 (三) 上一篇忘了ChanResult ChanResult 可以用来模拟BigPipe,定义如下 type ChanResult struct { Wait syn ...
- Go语言Web框架gwk介绍2
Go语言Web框架gwk介绍 (二) HttpResult 凡是实现了HttpResult接口的对象,都可以作为gwk返回Web客户端的内容.HttpResult接口定义非常简单,只有一个方法: ty ...
- Go语言Web框架gwk介绍 1
Go语言Web框架gwk介绍 (一) 今天看到Golang排名到前30名了,看来关注的人越来越多了,接下来几天详细介绍Golang一个web开发框架GWK. 现在博客园支持markdown格式发布 ...
- Go语言Web框架gwk介绍 (一)
今天看到Golang排名到前30名了,看来关注的人越来越多了,接下来几天详细介绍Golang一个web开发框架GWK. 现在博客园支持markdown格式发布文章么?后台的编辑器不太好用嘛. GWK ...
- Go语言Web框架gwk介绍 (五)
Session Go的net/http本身不带session的机制,需要开发人员自行实现,gwk实现了内存中的session存储机制,如果需要将session存在其他地方比如redis或者memcac ...
- Go语言Web框架gwk介绍 (四)
事件 gwk支持事件系统,但并没有硬编码有哪些事件,而是采用了比较松散的定义方式. 订阅事件有两种方式: 调用On函数或者OnFunc函数 func On(moudle, name string, h ...
- Go语言Web框架gwk介绍 (二)
HttpResult 凡是实现了HttpResult接口的对象,都可以作为gwk返回Web客户端的内容.HttpResult接口定义非常简单,只有一个方法: type HttpResult inter ...
- Go语言Web框架gwk介绍 (三)
上一篇忘了ChanResult ChanResult 可以用来模拟BigPipe,定义如下 type ChanResult struct { Wait sync.WaitGroup Chan chan ...
- 最好的6个Go语言Web框架
原文:Top 6 web frameworks for Go as of 2017 作者:Edward Marinescu 译者:roy 译者注:本文介绍截至目前(2017年)最好的6个Go语言Web ...
随机推荐
- 【百度地图API】建立全国银行位置查询系统(四)——如何利用百度地图的数据生成自己的标注
原文:[百度地图API]建立全国银行位置查询系统(四)--如何利用百度地图的数据生成自己的标注 摘要: 上一章留个悬念,"如果自己没有地理坐标的数据库,应该怎样制作银行的分布地图呢?&quo ...
- 菜鸟学Java(二十一)——怎样更好的进行单元測试——JUnit
測试在软件生命周期中的重要性,不用我多说想必大家也都很清楚.软件測试有许多分类,从測试的方法上可分为:黑盒測试.白盒測试.静态測试.动态測试等:从软件开发的过程分为:单元測试.集成測试.确认測试.验收 ...
- Windows Phone 8.1 多媒体(3):音乐
原文:Windows Phone 8.1 多媒体(3):音乐 Windows Phone 8.1 多媒体(1):相片 Windows Phone 8.1 多媒体(2):视频 Windows Phone ...
- Unix/Linux环境C编程新手教程(41) C语言库函数的文件操作具体解释
上一篇博客我们解说了怎样使用Linux提供的文件操作函数,本文主要解说使用C语言提供的文件操作的库函数. 1.函数介绍 fopen(打开文件) 相关函数 open,fclose 表头文件 #in ...
- AngularJS应用开发思维之2:数据绑定
在声明式模板中显示数据 因为不能像jQuery一样将DOM操作混在模板里,声明式模板很快让我们变得束手束脚. 一个典型的问题:在声明式模板里怎么显示数据? 假设我们有某人的基本信息,保存在一个json ...
- 通过扩展改善ASP.NET MVC的验证机制[实现篇]
原文:通过扩展改善ASP.NET MVC的验证机制[实现篇] 在<使用篇>中我们谈到扩展的验证编程方式,并且演示了本解决方案的三大特性:消息提供机制的分离.多语言的支持和多验证规则的支持, ...
- MVC+UnitOfWork+Repository+EF
MVC+UnitOfWork+Repository+EF UnitOfWork+Repository模式简介: 每次提交数据库都会打开一个连接,造成结果是:多个连接无法共用一个数据库级别的事务,也就无 ...
- Git基础教程
Git是一个分布式的版本控制工具,本篇文章从介绍Git开始,重点在于介绍Git的基本命令和使用技巧,让你尝试使用Git的同时,体验到原来一个版 本控制工具可以对开发产生如此之多的影响,文章分为两部分, ...
- Nginx搭建反向代理服务器
[大型网站技术实践]初级篇:借助Nginx搭建反向代理服务器 一.反向代理:Web服务器的“经纪人” 1.1 反向代理初印象 反向代理(Reverse Proxy)方式是指以代理服务器来接受int ...
- Ajax.ActionLink 用法
Ajax.ActionLink 用法 Ajax 属性的ActionLink方法可以创建一个具有异步行为的锚标签. ActionLink方法的第一个参数指定了链接文本,第二个参数是要异步调用的操作的名称 ...