2013-05-07 67 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