• 过滤器
    • 过滤器链配置
      • 全局配置
      • Per-Action configuration
    • 实现一个过滤器
      • 保持过滤器链能够依次执行
      • 获取控制器类型

    过滤器

    过滤器是Revel框架的中间件 – 是组成请求处理管道的独立的功能。他们执行框架的所有功能。

    过滤器类型是一个简单的函数:

    1. type Filter func(c *Controller, filterChain []Filter)

    每个过滤器负责调用过滤器链中的下一个过滤器。下面是个默认的过滤器栈:

    1. // Filters 是默认的全局过滤器集。
    2. // 可以在程序初始化时设置它。
    3. var Filters = []Filter{
    4. PanicFilter, // 从恐慌中恢复,并显示一个错误页面。
    5. RouterFilter, // 负责解析路由,并选择正确的控制器方法。
    6. FilterConfiguringFilter, // 用于添加/删除每个动作过滤的钩子。
    7. ParamsFilter, // 解析参数到 Controller.Params 中。
    8. SessionFilter, // 恢复和写入会话 cookie。
    9. FlashFilter, // 恢复和写入 flash cookie。
    10. ValidationFilter, // 恢复保存验证错误并保存新的Cookie中。
    11. I18nFilter, // 解析请求语言。
    12. InterceptorFilter, // 执行拦截器。
    13. ActionInvoker, // 调用控制器。
    14. }

    过滤器链配置

    全局配置

    程序可以在 init() 中重写 revel.Filters 变量,来配置过滤器链 (默认在 app/init.go)。

    1. func init() {
    2. // Filters 是默认的全局过滤器集。
    3. revel.Filters = []Filter{
    4. PanicFilter, // 从恐慌中恢复,并显示一个错误页面。
    5. RouterFilter, // 负责解析路由,并选择正确的控制器方法。
    6. FilterConfiguringFilter, // 用于添加/删除每个动作过滤的钩子。
    7. ParamsFilter, // 解析参数到 Controller.Params 中。
    8. SessionFilter, // 恢复和写入会话 cookie。
    9. FlashFilter, // 恢复和写入 flash cookie。
    10. ValidationFilter, // 恢复保存验证错误并保存新的Cookie中。
    11. I18nFilter, // 解析请求语言。
    12. InterceptorFilter, // 执行拦截器。
    13. ActionInvoker, // 调用控制器。
    14. }
    15. }

    每个请求沿着过滤器链从上到下依次执行。

    Per-Action configuration

    尽管所有的请求都被发往过滤器链 revel.Filters, Revel 也提供了 过滤器配置, 允许开发者根据操作或控制器添加、插入、删除过滤器。

    此功能通过 FilterConfiguringFilter 实现, 它本身就是一个过滤器.

    实现一个过滤器

    保持过滤器链能够依次执行

    Filters 负责依次调用下一个过滤器来依次处理请求。这通常需要完成下面的表达式:

    1. var MyFilter = func(c *revel.Controller, fc []revel.Filter) {
    2. // .. 做一些预处理 ..
    3.  
    4. fc[0](c, fc[1:]) // 执行下一个过滤器
    5.  
    6. // .. 做一些后期处理 ..
    7. }

    获取控制器类型

    Filters 接受一个 *Controller 类型的参数, 而不是被调用的实际的控制器类型。如果过滤器需要访问实际的控制器类型,可以这样实现:

    1. var MyFilter = func(c *revel.Controller, fc []revel.Filter) {
    2. if ac, err := c.AppController.(*MyController); err == nil {
    3. // 判定存在一个 *MyController 实例...
    4. }
    5.  
    6. fc[0](c, fc[1:]) // 执行下一个过滤器
    7. }

    注意:这种模式往往说明拦截器可能是实现所需功能的好的机制的一个指标。