论坛首页 Java企业应用论坛

grails源码分析---之Filters机制(2)

浏览 2258 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2008-11-11   最后修改:2008-11-11
我们写一个Filters跟踪分析一下Filters是如何变化加入到CompositeInterceptor的handlers成员
   
    class TestFilters {
    	def log ={
    		before = {
    				println "Before Filter"
    		}
    	}
    	
    	def filters = {
    		//这儿的方法名doFilter不重要,可以随便命名,为了调用闭包而已
    		doFilter([controller: '*', action: '*',uri:'*'],log)
    	}
    }
    

    DefaultGrailsFiltersClass.groovy
   
    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:'*"]和闭包log
	def 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
        }		
	}
}

    

    FilterConfig.groovy
   
    class FilterConfig {
	    String name
	    Map scope
	    Closure before
	    Closure after
	    Closure afterView
	    ...
	   }
    

    再看看FilterToHandlerAdapter进行FilterConfig到HandlerInterceptor的适配就很简单了,检查FilterConfig是否有before,after和afterView属性,再用scope属性验证当前ruquest的uri,controller和action
FilterToHandlerAdapter.groovy
//检查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()
      }
}
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics