2013-05-07 58 views
3

在我的Grails项目中,我想覆盖插件提供的过滤器,以便更好地满足我的需求。修改/覆盖由Grails插件提供的过滤器

更具体地说,过滤器被定义为适用于所有控制器上的所有操作:filterName(controller:"*", action:"*") { ... },我想将其限制为仅限某些控制器。

我试着在我的项目中创建一个与我想重写的过滤器同名的过滤器类,但结果是两个过滤器都在每个请求上执行。

所以没有人知道如何改变/覆盖/(甚至停用)插件提供的过滤器?提前致谢!

回答

2

dmahapatro的回答使我找到了解决方案:关键概念是访问filterInterceptor bean,其中包含Grails应用程序中所有过滤器的定义。它可以被访问,例如在BootStrap.groovy文件,以便在应用程序启动来修改可用的过滤器:

class BootStrap { 
    def filterInterceptor 

    def init = { servletContext -> 
     // modify myPluginFilter provided by plugin so it 
     // is only applied to certain requests 
     def myPluginFilterHandler = filterInterceptor.handlers.find{ it.filterConfig.name == 'myPluginFilter' } 
     myPluginFilterHandler.filterConfig.scope.controller = 'myController' 
     myPluginFilterHandler.filterConfig.scope.action = 'myAction' 
     myPluginFilterHandler.afterPropertiesSet() 

     log.info "myPluginFilter scope modified" 
    } 

    ... 
} 

该代码在应用程序启动时执行一次,它找到的滤波器myPluginFilter(例如,在一个插件中定义),并改变它的范围(所述控制器并采取行动)。

该过滤器可能会被破坏,而不是通过从filterInterceptor.handlers集合中删除myPluginFilterHandler来重新定义。

+0

该解决方案的缺点是,如果过滤器定义被重新加载(例如,当过滤器被修改或在开发模式下添加时),修改后的过滤器将保持其原始定义,因为'BootStrap.groovy'中的代码仅在执行一次应用程序启动。但是,这在生产模式中应该不成问题。 – 2013-05-09 13:45:12

+0

我去了一个解决方案,我有一个插件,指定'def loadAfter = ['filters']',然后在'doWithApplicationContext'修改'filterInterceptor' bean上的处理程序集合 – erdi 2013-10-31 13:53:57

0

您可以尝试clearing从新的过滤器类的handlers在您的项目是这样的:

blockPluginFilter(controller:"*", action:"*"){ 
    before = { 
     def compInterceptor = applicationContext.getBean("filterInterceptor", CompositeInterceptor) 
     compInterceptor.handlers?.clear() 
    } 
} 

每个filter有一个配置的Spring bean filterInterceptor注册为CompositeInterceptor它有一个手柄来表示为所有filtershandlers。如果您在新过滤器中清除handlers(如果它不晚),则可以避免执行plugin中的filter。您可以在项目过滤器类中创建另一个过滤器来处理您的自定义逻辑。只有插件的过滤器在该过滤器之后执行时,这才会起作用。在插件过滤器被击中之前,您可以在其他任何地方清除handlers

+0

感谢您的回答;它让我深入了解如何在运行时以编程方式修改过滤器定义。我通过在'BootStrap.groovy'中只访问'filterInterceptor'来修改解决方案,然后更改过滤器的定义。我把它作为一个单独的anwer发布并接受它。 – 2013-05-09 13:46:52