grailsソース分析---のFiltersメカニズム(2)

5545 ワード

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、after View属性があるかどうかを確認し、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()
      }
}