grails源码分析---之Filters机制(2)
我们写一个Filters跟踪分析一下Filters是如何变化加入到CompositeInterceptor的handlers成员
class TestFilters { def log ={ before = { println "Before Filter" } } def filters = { //这儿的方法名doFilter不重要,可以随便命名,为了调用闭包而已 doFilter([controller: '*', action: '*',uri:'*'],log) } } class DefaultGrailsFiltersClass extends AbstractInjectableGrailsClass implements GrailsFiltersClass { static FILTERS = "Filters"; //grails类必须的构造函数,可以让FiltersGrailsPlugin找到 DefaultGrailsFiltersClass(Class aClass) { super(aClass, FILTERS) } public List getConfigs(Object filters) { if (!filters) return []; def loader = new Loader(filters) //找到TestFilters的filters闭包属性 def filtersClosure = filters.filters filtersClosure.delegate = loader //调用闭包即doFilter([controller: '*', action: '*',uri:'*"],log),生成FilterConfig对象数组 filtersClosure.call() return loader.filters; }}class Loader { def filtersDefinition def filters = [] Loader(filtersDefinition) { this.filtersDefinition = filtersDefinition }//调用闭包即filter([controller: '*', action: '*',uri:'*"],log)//methodName=doFilter,args是[controller: '*', action: '*',uri:'*"]和闭包logdef methodMissing(String methodName, args) { if(args) { def fc = new FilterConfig(name: methodName, filtersDefinition: filtersDefinition) filters << fc if(args[0] instanceof Closure) { fc.scope = [ uri: '/**' ] def closure = args[0] closure.delegate = fc closure.call() } else if(args[0] instanceof Map) { fc.scope = args[0] if(args.size() > 1 && args[1] instanceof Closure) { def closure = args[1] closure.delegate = fc //args[1]即是TestFilters的log闭包,调用对象delegate是FilterConfig closure.resolveStrategy = Closure.DELEGATE_FIRST //log闭包调用的第一句就是before= {...},而FilterConfig就有一个before的闭包属性 //这样fc.before即为TestFilters中的before闭包,fc.scope即为[controller: '*', action: '*',uri:'*"] closure.call() } } fc.initialised = true }}} class FilterConfig { String name Map scope Closure before Closure after Closure afterView ... } //检查grails的controllerName,actionName,uri是否boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) { if (filterConfig.before) { String controllerName = controllerName(request) String actionName = actionName(request) String uri = uri(request) if (!accept(controllerName, actionName, uri)) return true; def callable = filterConfig.before.clone() def result = callable.call(); if(result instanceof Boolean) { if(!result && filterConfig.modelAndView) { renderModelAndView(filterConfig, request, response, controllerName) } return result } } return true; }boolean accept(String controllerName, String actionName, String uri) { if (controllerRegex == null || actionRegex == null) { def scope = filterConfig.scope if (scope.controller) { controllerRegex = Pattern.compile(scope.controller.replaceAll("\\*", ".*")) } else { controllerRegex = Pattern.compile(".*") } if (scope.action) { actionRegex = Pattern.compile(scope.action.replaceAll("\\*", ".*")) } else { actionRegex = Pattern.compile(".*") } if (scope.uri) { uriPattern = scope.uri.toString() } } if(uriPattern) { return pathMatcher.match(uriPattern, uri) } else if(controllerRegex && actionRegex) { return controllerRegex.matcher(controllerName).matches() && actionRegex.matcher(actionName).matches() }}