beego过滤器及自定义标签

在开始学习beego的过滤器之前,说一个项目开发中遇到的一个bug,这个bug是hybris自己的,导致项目上线后backoffice的一些功能出现问题,当时在服务器上看到日志显示的是某个bean创建失败,原因是依赖类型错误,就是它需要的属性是A类型,但是实际却是B类型。自己查看了spring-bean的配置文件发现有重名bean的情况,但是这两个bean定义的配置文件不同,所以配置文件并不会报错。自己又看了下相应的代码,发现它采用的注解是@Resource,我们知道这个注解是java自身的注解,它注入的时候是按名称注入的,而spring默认采用的单列,也就是说spring创建bean的时候会去查看容器内是否有同名的bean存在,不存在才会创建新的bean。这就是这个bug问题所在,因为bean同名,导致需要类型A的bean没有创建,因为容器内已经有同名但类型为B的bean,因此导致了创建该bean错误,这应该是问题原因。所以最后方法就是修改一个配置文件中bean的别名以及相关的代码。个人觉得如果将注解换成@Autowired,即按照类型注入,应该也能解决这个问题,但是这里还会有个问题,就是如果该类型有多个实现可能依然会出错。spring采用配置文件方式开发,因为有多个配置文件,所以定义bean的时候一定要注意这一点。

beego过滤器

接下来继续学习beego的框架的过滤器,关于beego框架我还是抱着了解和掌握的,不会去过多的学习,毕竟框架这么多,很难什么都去兼顾。个人觉得学习的重点还是应该放在语言本身,go如此,java也一样。上次学习beego的时候说过beego的过滤器和springmvc的拦截器有相似之处,过滤器也好拦截器也罢其实用处大同小异,那就是hold住用户请求以便做一些相关处理。
beego的过滤器函数如下:

beego.InsertFilter(pattern string, position int, filter FilterFunc, params ...bool)

第一个参数表示过滤的路由规则,支持通配符,这点和java的过滤器、拦截器一样;
第二个参数就是过滤器的位置,这个值是个常量,beego支持的有5种,即:BeforeStatic 静态地址之前,BeforeRouter 寻找路由之前,BeforeExec 找到路由之后,但是在执行相应的 controller 之前,AfterExec 执行完 controller 之后执行,FinishRouter 执行完整个逻辑之后执行。
第三个参数为可选参数,都是bool类型。第一个设置 returnOnOutput 的值(默认 true), 即如果有输出是否跳过其他过滤器,默认只要有输出就不再执行其他过滤器,即执行完controller之后不会执行后面的过滤器;第二个表示是否重置过滤器的参数,默认是 false。关于这两个参数的区别看下下面的例子。
首先在main函数里面添加所有的过滤器,并且将过滤器函数的第三个参数全部显性的设置成默认值,代码如下:

func main() {
    // 过滤器
    beego.InsertFilter("/*", beego.BeforeExec, controllers.BeforeExecFilter,true,false)
    beego.InsertFilter("/*", beego.BeforeRouter, controllers.BeforeRouterFilter,true,false)
    beego.InsertFilter("/*", beego.BeforeStatic, controllers.BeforeStaticFilter,true,false)
    beego.InsertFilter("/*", beego.AfterExec, controllers.AfterExecFilter,true,false)
    beego.InsertFilter("/*", beego.FinishRouter, controllers.FinishRouterFilter,true,false)

    // run方法前注册错误handler
    beego.ErrorController(&controllers.ErrorController{})

    beego.Run()
}

然后启动项目并访问,看下日志输出情况:


图-001.png

根据日志输出内容可以看出过滤器的执行顺序,但是我们发现controller执行后的过滤器没有执行,这是因为这个controller有输出,所以之后的过滤器没有执行,改成false再执行一次看下日志输出结果


图-002.png

根据修改后的日志可以看出,AfterExecFilter和FinishRouterFilter在controller执行后都执行了,所以如果需要在controller执行后做一些操作的话一定要将这个参数设置陈false。
第二个bool类型的参数表示是否重置过滤器的参数,即在执行过滤器的时候是否重置 :splat 参数,关于这一点我看了一下文档,不是特别清楚什么意思,而且我设置成true和false分别访问没有看出有什么不同的地方,我也没理解它的用途到底是什么,我官方文档提问了,如果有答案我再来更新吧。

使用过滤器的时候如果有用到session,必须在BeforeStatic过滤器之后才能使用,因为在BeforeStatic之前,session没有初始化。


自定义标签

接下来更正一个上次的错误,就是关于数据模型定义的。先看一下上次用到的一个数据模型代码:

type User struct {
    Id       int    
    UserName string 
    Age      int    
    Sex      string 
    Mobile   string 
    Password string
    Email    string 
}

对于数据模型一般我们都会使用go的标签来重新命名,比如转json或者form表单转对象以及和数据库表的列名对应等等。在和数据库表映射时,如果不专门指定表的列名,那么名称转换的时候可能会出现问题,比如上面定义的User,UserName会转换成user_name,如果数据库的列名是username,那么查询的时候就会出现问题,所以一般会指定字段名称,比如我就想将UserName用username表示,那么需要使用"orm标签"而不是"column"标签,上次代码中我的表达方式是这样的:

UserName string `form:"username"  column:"username" json:"userName"`

因为当时我的数据库列名是user_name,自己当时没有发现这个问题,以为"column"标签生效,结果这次重新安装postgresql自己定义表后发现了问题,即"column"标签是错误的,正确的用法应该如下:

UserName string `form:"username"  orm:"column(username)" json:"userName"`

到这里可能很多小伙伴就会比较好奇,go到底有多少标签(Tag)??除了"form、json、orm"还有没有其他标签,当然是有的,但是需要明白一点这些标签中orm是beego框架的,如果使用的是其他ORM框架,比如gorm,使用"orm"标签是无效的,应该使用"gorm"。go语言本身自带的有"json、xml、form",也可能还有其他的只是我不知道而已。记得上次学习beego入门的时候说过,go的标签可以看作是java的注解,至少部分功能上相同。我们知道java是可以自定义注解,然后通过反射的形式来获取对应的名称和值的,go也是一样,也可以自定义标签,并指定相应的值,然后通过反射获取,通过一个简单的代码来看一下:

// 自定义标签
type CustomStruct struct {
    Name        string   `customTag:"userName" tags:"user_name"`
    Password    string   `customTag:"pwd"`
    Age         int      `customTag:"userAge"`
}
func main() {
    cust := CustomStruct{"张三", "123456", 22}
    t := reflect.TypeOf(cust)
    //val := reflect.ValueOf(cust)
    //for i := 0; i < val.NumField(); i++ {
    //  println(val.Field(i).Kind().String())
    //}

    field, _ := t.FieldByName("Name")
    println(">>>> custom struct field Tag=" + field.Tag + " <<<<")
    println(">>>> struct field name's customTag value=" + field.Tag.Get("customTag") + " <<<<")
    v, _ := field.Tag.Lookup("tags")
    println(">>>> struct field name's tags value=" + v + " <<<<")
    field, _ = t.FieldByName("Password")
    println(">>>> struct field password's tag=" + field.Tag + " <<<<")
    field, _ = t.FieldByName("Age")
    println(">>>> struct field age's tag=" + field.Tag + " <<<<")
}

首先创建一个struct结构,并设置了3个属性,然后使用了自定义的Tag,其中Name属性使用了两个自定义Tag。main函数中首先初始化了一个对象,然后通过反射获取其类型,获取类型之后得到了属性,然后对属性进行操作获取自定义标签的Tag或者某个Tag名称的值,以标签的名称为key获取value时使用了Get("key")和Lookup("key")两种方式,其实Get就是调用的Lookup。程序运行后最终的输出结果如下:

>>>> custom struct field Tag=customTag:"userName" tags:"user_name" <<<<
>>>> struct field name's customTag value=userName <<<<
>>>> struct field name's tags value=user_name <<<<
>>>> struct field password's tag=customTag:"pwd" <<<<
>>>> struct field age's tag=customTag:"userAge" <<<<

go的反射相对java来讲感觉弱了一点,当然自己只是感觉,毕竟反射这部分内容自己还没有好好的去学习,也是今天用到了Tag临时看了一下。但是其实这里我还有个疑问,就是如何才知道我的struct属性上定义了多少个Tag以及Tag的名称是什么应该怎么获取?根据上面输出的情况看,即使某个属性有多个不同类型的标签,输出的时候这个Tag都是一个整体,而Tag只提供了Get("key")和Lookup("key")两个方法。如果真的想获取Tag的数量以及名称,只能自己来实现了。
今天的学习就到这里,内容相对比较少,而且自己对框架不是很热衷,我觉得需要的时候在学习也是来的及的。除了MVC和ORM之外beego其他内置的模块自己暂时不会去学习,比如session、httplib、cache等等,当然这些内容其实都是非常值得一学的,但是因为自己现在没有在做专门的go开发,所以我觉得重点还是放到语言本身更好一些。
代码已经更新到我的github

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,287评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,346评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,277评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,132评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,147评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,106评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,019评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,862评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,301评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,521评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,682评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,405评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,996评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,651评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,803评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,674评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,563评论 2 352

推荐阅读更多精彩内容

  • 文章作者:Tyan博客:noahsnail.com 3.4 Dependencies A typical ente...
    SnailTyan阅读 4,151评论 2 7
  • 今天主要来简单学习一下beego,一个比较流行的go框架。前段时间学习了go语言的基础,対go算是有了一个简单了解...
    非典型_程序员阅读 33,628评论 1 12
  • 1 同事小洁在北京四环外租了一套两室一厅的房子,由于房租很高,于是小洁决定把其中一间转租出去,以缓解压力。 房子宽...
    小静读童书阅读 447评论 0 3
  • 忽见女儿录取单 心潮汹涌如浪翻 寒窗苦读几月整 只为圆我求学梦 以往基础比人差 勤学苦练未落下 人生短暂抓机遇 此...
    端阳香草阅读 242评论 0 4
  • 搬家 又是枫残栗落时,随阳蓬舍始平基, 泥浆弥缝风难入,湿木填炉火更滋, 雪里炊烟千段舞,冰中湖水百寻诗, 此身藏...
    落石泉阅读 270评论 0 4