过滤器是Revel框架的中间件 – 是组成请求处理管道的独立的功能。他们执行框架的所有功能。
过滤器类型是一个简单的函数:
~~~
type Filter func(c *Controller, filterChain []Filter)
~~~
每个过滤器负责调用过滤器链中的下一个过滤器。下面是个默认的过滤器栈:
~~~
// Filters 是默认的全局过滤器集。
// 可以在程序初始化时设置它。
var Filters = []Filter{
PanicFilter, // 从恐慌中恢复,并显示一个错误页面。
RouterFilter, // 负责解析路由,并选择正确的控制器方法。
FilterConfiguringFilter, // 用于添加/删除每个动作过滤的钩子。
ParamsFilter, // 解析参数到 Controller.Params 中。
SessionFilter, // 恢复和写入会话 cookie。
FlashFilter, // 恢复和写入 flash cookie。
ValidationFilter, // 恢复保存验证错误并保存新的Cookie中。
I18nFilter, // 解析请求语言。
InterceptorFilter, // 执行拦截器。
ActionInvoker, // 调用控制器。
}
~~~
## 过滤器链配置
### 全局配置
程序可以在 `init()` 中重写 `revel.Filters` 变量,来配置过滤器链 (默认在 `app/init.go`)。
~~~
func init() {
// Filters 是默认的全局过滤器集。
revel.Filters = []Filter{
PanicFilter, // 从恐慌中恢复,并显示一个错误页面。
RouterFilter, // 负责解析路由,并选择正确的控制器方法。
FilterConfiguringFilter, // 用于添加/删除每个动作过滤的钩子。
ParamsFilter, // 解析参数到 Controller.Params 中。
SessionFilter, // 恢复和写入会话 cookie。
FlashFilter, // 恢复和写入 flash cookie。
ValidationFilter, // 恢复保存验证错误并保存新的Cookie中。
I18nFilter, // 解析请求语言。
InterceptorFilter, // 执行拦截器。
ActionInvoker, // 调用控制器。
}
}
~~~
每个请求沿着过滤器链从上到下依次执行。
### Per-Action configuration
尽管所有的请求都被发往过滤器链 `revel.Filters`, Revel 也提供了 [`过滤器配置`](http://gorevel.cn/docs/docs/godoc/filterconfig.html#FilterConfigurator), 允许开发者根据操作或控制器添加、插入、删除过滤器。
此功能通过 `FilterConfiguringFilter` 实现, 它本身就是一个过滤器.
## 实现一个过滤器
### 保持过滤器链能够依次执行
Filters 负责依次调用下一个过滤器来依次处理请求。这通常需要完成下面的表达式:
~~~
var MyFilter = func(c *revel.Controller, fc []revel.Filter) {
// .. 做一些预处理 ..
fc[0](c, fc[1:]) // 执行下一个过滤器
// .. 做一些后期处理 ..
}
~~~
### 获取控制器类型
Filters 接受一个 `*Controller` 类型的参数, 而不是被调用的实际的控制器类型。如果过滤器需要访问实际的控制器类型,可以这样实现:
~~~
var MyFilter = func(c *revel.Controller, fc []revel.Filter) {
if ac, err := c.AppController.(*MyController); err == nil {
// 判定存在一个 *MyController 实例...
}
fc[0](c, fc[1:]) // 执行下一个过滤器
}
~~~
注意:这种模式往往说明[拦截器](http://gorevel.cn/docs/manual/interceptors.html)可能是实现所需功能的好的机制的一个指标。