阅读更多
先摘录一段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了。