`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/cnblogs_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:]) // 执行下一个过滤器栈
}

Go Revel - Filters(过滤器链)的更多相关文章

  1. Spring Security过滤器链体系

    以下摘自胖哥分享的 2022开工福利教程. 在学习Spring Security的时候你有没有下面这两个疑问: Spring Security的登录是怎么配置的? Spring Security的访问 ...

  2. Liferay7 BPM门户开发之36: 使用Portlet filters过滤器做切面AOP

    使用Portlet filters过滤器做切面AOP Portlet Filters定义于JSR286 Java Portlet Specification 2.0 Portlet Filters是为 ...

  3. Asp.Net MVC 3【Filters(过滤器)】

    这里分享MVC里的Filters(过滤器),什么是MVC里的过滤器,他的作用是什么? 过滤器的请求处理管道中注入额外的逻辑.他们提供了一个简单而优雅的方式来实现横切关注点.这个术语是指所有对应用程序的 ...

  4. vue filters过滤器

    vue filters过滤器 vue.js允许我们自定义过滤器,可被使用于一些常见的文本格式化,过滤器可以用在两个地方,双花括号插值和 v-bind表达式.最常见的就是双花括号插值. 比如如下代码:{ ...

  5. spring boot 自定义过滤器链

    spring boot 会按照order值的大小,从大到小的顺序来依次过滤. 贴下代码: package com.osp.ucenter; import org.springframework.boo ...

  6. Vue.js Cookbook: 添加实例属性; 👍 axios(4万➕✨)访问API; filters过滤器;

    add instance properties //加上$,防止和已经定义的data,method, computed的名字重复,导致被覆写.//可以自定义添加其他符号. Vue.prototype. ...

  7. .net core MVC 通过 Filters 过滤器拦截请求及响应内容

    前提: 需要nuget   Microsoft.Extensions.Logging.Log4Net.AspNetCore   2.2.6: Swashbuckle.AspNetCore 我暂时用的是 ...

  8. 过滤器链chain.doFilter(request,response)含义

    过滤器的生命周期一般都要经过下面三个阶段: 初始化 当容器第一次加载该过滤器时,init() 方法将被调用.该类在这个方法中包含了一个指向 Filter Config 对象的引用. 过滤 过滤器的大多 ...

  9. Spring Security(2):过滤器链(filter chain)的介绍

    上一节中,主要讲了Spring Security认证和授权的核心组件及核心方法.但是,什么时候调用这些方法呢?答案就是Filter和AOP.Spring Security在我们进行用户认证以及授予权限 ...

随机推荐

  1. OpenGL tutorial资源在mac yosemite下的cmake生成工程问题

    如果你在使用cmake -G Xcode -Wno-dev OpenGL_Tutorial 时,出现了pThread.h not found的错误, 碰巧你和我一样使用的还是 2.8 版本的cmake ...

  2. com.mysql.jdbc.PacketTooBigException: Packet for query is too large (1169 > 1024)

    ### Cause: com.mysql.jdbc.PacketTooBigException: Packet for query is too large (1169 > 1024). You ...

  3. 在ubuntu14系统中将redis-server设置为开机启动项

    1.redis安装完成后(我装的是redis-3.0.7),修改配置文件redis.conf,修改的项目如下 注意:以下内容都是在root用户下进行操作的 gedit redis.conf打开文件进行 ...

  4. mysql中查询一个字段属于哪一个数据库中的哪一个表的方式

    mysql中查询一个字段具体是属于哪一个数据库的那一张表:用这条语句就能查询出来,其中 table_schema 是所在库, table_name 是所在表 --mysql中查询某一个字段名属于哪一个 ...

  5. 讲讲python“=”运算符上的优雅语法

    心路历程: 之前学linux,虽然学的行算不错,不过总感觉差了点什么,自己找不到也说不出来:直到有一天我看到别人mount上了一个普通文件: 当时给我的感觉这太不可思议了,这个文件又不是块设备:后来脑 ...

  6. MongoDB联合查询 -摘自网络

    1.简单手工关联 首先将结果查询出来放到一个变量里面,然后再查询 u = db.user.findOne({author:"wangwenlong"}); for(var p = ...

  7. 使用vlc实现视频TS流的推送

    鉴于Mpeg TS流播放的需求,使用 VLC作为Server来实现输出Mpeg TS    本文仅涉及如何使用VLC的Command来实现作为视频流Server通常可以使用下述四种方式来推送Mpeg ...

  8. Android Studio 1.1.0 向导页(首页) 解析,以及版本控制 (SVN 和 GIT 的检出)

    使用Android Studio首先要理清楚, Android Studio 的 project  相当于Eclipse的 Workspace Android Studio 的 module 相当于E ...

  9. Requests: 让 HTTP 服务人类

    requests 2.18.1文档 requests流式post文件 Calling SOAP Web service using requests module of

  10. socket.io笔记三之子命名空间的socket连接

    当客户端发送admin命名空间下的连接,如果主连接也监听了connetion事件,主连接的connection事件会先触发执行,然后紧接着触发执行admin命名空间下的connection事件.如果客 ...