Grails中的过滤器(Filter)和拦截器(Interceptor)

先摘录一段Java中两者的区别
1、拦截器是基于java的反射机制的,而过滤器是基于函数回调 。
2、过滤器依赖与servlet容器,而拦截器不依赖与servlet容器 。
3、拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用 。( 这也就是为什么在Grails文档里,拦截器属于Controlloer章节的一个小节;而过滤器自己是一个章节
4、拦截器可以访问action上下文、值栈里的对象,而过滤器不能 。
5、在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次 。

Grails的文档是这样描述的
If your interceptor is likely to apply to more than one controller, you are almost certainly better off writing a Filter. Filters can be applied to multiple controllers or URIs without the need to change the logic of each controller
所以,对于登陆验证,filter更加适合,默默的、悄悄的,减少继承。
interceptor更加适合处理一个controller内的特殊情况。



拦截器
abstract class BaseController {  //需要验证的Controller继承之
    def beforeInterceptor = [action: this.&auth, except: ['login']]

    private def auth() {
        if (!session.loginUser) {
            redirect(controller: 'user', action: 'login')
            return false
        }
    }
}

过滤器
grails create-filters security

class SecurityFilters {
    def filters = {
        loginCheck(controller: '*', action: '*', uriExclude: '/user/login') {
            before = {
                if (!session.loginUser) {
                    redirect(controller: 'user', action: 'login')
                    return false
                }
            }
        }
    }
}

有趣的测试,如果同时设置了拦截器和过滤器,过滤器(是容器级的)工作在拦截器(Controller级的)之前。


补充一个遇见的bug
可以绕开
loginCheck(controllerExclude:'sample',actionExclude:'createAdmin')
可以绕开
loginCheck(uriExclude:'/user/login')
可以绕开/user/login,但是/sample/createAdmin绕不开。。。
loginCheck(controllerExclude:'sample',actionExclude:'createAdmin', uriExclude:'/user/login')

其实是因为目前的bug,说是Grails 2.3的时候能解决
http://jira.grails.org/browse/GRAILS-3137?actionOrder=desc
Multiple URI Filters in form of a list don't work anymore (since 1.0.3)
推测:controller, action最终都会被转化为uri的形式,所以就出现两个URI了,就调入bug了。

猜你喜欢

转载自jcat.iteye.com/blog/1766283