`
bloodwolf_china
  • 浏览: 129756 次
社区版块
存档分类
最新评论

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

阅读更多
    grails提供了两种对请求的拦截机制,一是在Controller中定义beforeInterceptor和afterInterceptor两个方法,分别在执行action之前和之后调用,具体实现代码是在SimpleGrailsController和SimpleGrailsControllerHelper中,不再赘述。
    还有一个是Filter,即在grails-app/conf目录下定义以Filters结尾的groovy文件既可,提供了三个拦截方法before,after,afterView,分别对应Spring MVC的HandlerInterceptor接口的preHandle(在处理请求前调用),postHandle(在处理请求后生成View之前调用,提供了修改Model的机会),afterCompletion(在请求处理完毕生成View之后调用)。
看看源码即可发现其实grails的MVC即是在Spring MVC框架上包装一层而成的,所以看来暂时不可能把核心框架修改为struts的可能。
    下面看看grails是如何把Filters结尾的groovy文件变成Spring的HandlerInterceptor。
    DefaultGrailsPlugin加载所有的plugin,当然也包含FiltersGrailsPlugin
    DefaultGrailsPlugin.groovy
   
    //加载plugin,调用plugin的doWithApplicationContext方法
    public void doWithRuntimeConfiguration(
            RuntimeSpringConfiguration springConfig) {

        if(this.pluginBean.isReadableProperty(DO_WITH_SPRING)) {
            if(LOG.isDebugEnabled()) {
                LOG.debug("Plugin " + this + " is participating in Spring configuration...");
            }
            //调用plugin的doWithSpring方法,加载plugin到spring的ApplicationContext,使用Spring DSL方式的BeanBuilder 
            Closure c = (Closure)this.plugin.getProperty(DO_WITH_SPRING);
            BeanBuilder bb = new BeanBuilder(getParentCtx(), application.getClassLoader());
            bb.setSpringConfig(springConfig);
            Binding b = new Binding();
            b.setVariable("application", application);
            b.setVariable("manager", getManager());
            b.setVariable("plugin", this);
            b.setVariable("parentCtx", getParentCtx());
            b.setVariable("resolver", getResolver());
            bb.setBinding(b);
            c.setDelegate(bb);
            bb.invokeMethod("beans", new Object[]{c});
        }

    }
    	//动态配置plugin,调用plugin的doWithApplicationContext方法
     public void doWithApplicationContext(ApplicationContext applicationContext)
    

    FiltersGrailsPlugin.groovy
   
    def watchedResources = "file:./grails-app/conf/**/*Filters.groovy"
    //Spring bean DSL
    static final BEANS = { filter ->
            "${filter.fullName}Class"(MethodInvokingFactoryBean) {
                targetObject = ref("grailsApplication", true)
                targetMethod = "getArtefact"
                arguments = [TYPE, filter.fullName]
            }
            "${filter.fullName}"(filter.clazz) { bean ->
                bean.singleton = true
                bean.autowire = "byName"
            }
    }
    //生成了实现spring HandlerInterceptor接口的filterInterceptor
    def doWithSpring = {
		filterInterceptor(org.codehaus.groovy.grails.plugins.web.filters.CompositeInterceptor) {

        }

        for(filter in application.getArtefacts(TYPE)) {
            def callable = BEANS.curry(filter)
            callable.delegate = delegate
            callable.call()
        }
	}
	
	def doWithApplicationContext = { applicationContext ->
        reloadFilters(application, applicationContext)
	}
	
	
	//   把Filters groovy类变成CompositeInterceptor的handlers成员
	//  用FilterToHandlerAdapter适配器把preHandle==before,postHandle==after,afterCompletion==afterView对应起来
	private reloadFilters(GrailsApplication application, applicationContext) {
        log.info "reloadFilters"
        def filterConfigs = application.getArtefacts(TYPE)
        def handlers = []
        for(c in filterConfigs) {
            def filterClass = applicationContext.getBean("${c.fullName}Class")
            def bean = applicationContext.getBean(c.fullName)
            for(filterConfig in filterClass.getConfigs(bean)) {
                handlers << new FilterToHandlerAdapter(filterConfig:filterConfig, configClass:bean)
            }
        }

        if (log.isDebugEnabled()) log.debug("resulting handlers: ${handlers}")
        applicationContext.getBean('filterInterceptor').handlers = handlers
    }
    

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics