grailsソース分析---のFiltersメカニズム(2)
Filtersトラッキングを書いて、FiltersがCompositeInterceptorに加入したhandlersメンバーにどのように変化したかを分析します.
DefaultGrailsFiltersClass.groovy
FilterConfig.groovy
FilterToHandlerAdapterがFilterConfigからHandlerInterceptorへの適合を行うのは簡単です.FilterConfigにbefore、after、after View属性があるかどうかを確認し、scope属性で現在のruquestのuri、controller、actionを検証します.
FilterToHandlerAdapter.groovy
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()
}
}