Go Revel - Filters,过滤器链

`Fitlers`过滤器链是一个中间件,它们具有单独的功能,并作为管道对请求做链式处理。过滤器链执行框架的所有功能。 对过滤器链的源码分析,请移步 Go Revel - Filter(过滤器)源码分析 http://www.cnblogs.com/hangxin1940/p/3266311.html 一个过滤器这样定义: type Filter func(c *Controller, filterChain []Filter) 没一个过滤器负责拉取下一个过滤器并执行它。下面是所有过滤器的调用堆栈: var Filters = []Filter{ PanicFilter, // 运行时异常过滤器 恢复一个 panics 运行时异常并且显示异常信息页面 RouterFilter, // 路由过滤器 根据路由器选择正确的Action FilterConfiguringFilter, // 自定义过滤器配置器 为每一个Action增加或删除自定义过滤器 ParamsFilter, // 参数转换过滤器 将请求的参数转换为 Controller.Params SessionFilter, // 会话过滤器 恢复和写入会话cookie FlashFilter, // Flash过滤器 恢复和写入Flash信息cookie ValidationFilter, // 验证过滤器 恢复保存验证错误并且从cookie中新建一个 I18nFilter, // i18n过滤器 解析请求的语言 InterceptorFilter, // 拦截器过滤器 在Action前后运行拦截器 ActionInvoker, // Action过滤器 调用Action方法 } ![golang_filters](http://images.cnblogs.com/likecs_com/hangxin1940/508415/o_golang-revel-filters.png "golang_filters") ##配置过滤器链 **全局配置** 应用程序可以在`init()`方法内重新分配`revel.Filters`变量中的过滤器顺序。(在使用revel生成新的应用时会在`app/init.go`中构造默认的过滤器链) func init() { revel.Filters = []Filter{ PanicFilter, // 运行时异常过滤器 恢复一个 panics 运行时异常并且显示异常信息页面 RouterFilter, // 路由过滤器 根据路由器选择正确的Action FilterConfiguringFilter, // 自定义过滤器配置器 为每一个Action增加或删除自定义过滤器 ParamsFilter, // 参数转换过滤器 将请求的参数转换为 Controller.Params SessionFilter, // 会话过滤器 恢复和写入会话cookie FlashFilter, // Flash过滤器 恢复和写入Flash信息cookie ValidationFilter, // 验证过滤器 恢复保存验证错误并且从cookie中新建一个 I18nFilter, // i18n过滤器 解析请求的语言 InterceptorFilter, // 拦截器过滤器 在Action前后运行拦截器 ActionInvoker, // Action过滤器 调用Action方法 } } 每一个请求都会按从上到下的顺序交给每个过滤器处理。 **每个Action的配置** 尽管所有请求都沿着`revel.Filters`过滤器链向下运行,但是revel也提供了`FilterConfigurator`,允许围绕`controller`或`action`方便的对其添加、插入和删除自定义过滤器栈。 `FilterConfiguringFilter`实现了这些功能,而且它本身就是一个过滤器栈。 ##实现一个过滤器 **保持管道链的继续运行** 过滤器负责调用下一个过滤器来继续对请求的处理。 var MyFilter = func(c *revel.Controller, fc []revel.Filter) { // .. 在调用之前做些处理 .. fc[0](c, fc[1:]) // 执行下一个过滤器栈. // .. 逐个退出过滤器栈 .. } **获取Controller控制器类型** 过滤器将`*Controller`类型作为地一个传入的参数,而不是实际调用的 Controller 类型,如果过滤器需要对实际调用的controller进行操作,可以使用如下技巧: var MyFilter = func(c *revel.Controller, fc []revel.Filter) { if ac, err := c.AppController.(*MyController); err == nil { // 取得一个 *MyController 实例... } fc[0](c, fc[1:]) // 执行下一个过滤器栈 }