2010-11-04 39 views
5

我有如下定義的過濾器。他們在各個地方運行相同的代碼塊,因此爲了保持乾爽,我將該代碼重構爲一個名爲doResponse()的方法。從Grails中的過濾器幫助器方法調用render()

class MyFilters { 

    def filters = { 
     web(uri: '/web/**') { 
      before = { 

       // Do Stuff 
       if (condition) { 
        doResponse(request, response, params) 
       } 
       return true 
      } 
      after = { 
       if (condition) { 
        doResponse(request, response, params) 
       } 
       else { 
        // Do Stuff 
        doResponse(request, response, params) 
       } 

      } 
      afterView = { 
      } 
     } 
    } 

    boolean doResponse(request, response, params) { 
    // Do Stuff 
     render(status: statusCode, contentType: "text/xml", encoding: "ISO-8859-1", text: text) 
    // Do post-render stuff 
     return false 
    } 
} 

然而,這有一個令人討厭的副作用。看起來render()方法只能在filters閉包中使用。有什麼(整潔)的方式讓我從doResponse()調用render()?

編輯:我得到的錯誤是:

groovy.lang.MissingMethodException:法無簽名:MyFilters.render()的參數類型是適用的:(java.util.LinkedHashMap中)值:[狀態:500,contentType:text/xml,encoding:ISO-8859-1,text:...]]

回答

8

傳遞定義render(..)方法將doRespond(..)方法的對象,並且調用該對象上的render(..)方法。

閉包有一些implicit variables,包括它們的owner,指的是父閉包;所以我們可以傳遞:

if (condition) { 
    doResponse(owner, request, response, params) 
} 

doRespond(..)方法:

boolean doResponse(webFilter, request, response, params) { 
    // Do Stuff 
    webFilter.render(status: statusCode, contentType: 
     "text/xml", encoding: "ISO-8859-1", text: text) 
    // Do post-render stuff 
    return false 
} 
+0

嗨我試圖做到這一點,但得到:java.lang.NullPointerException:無法設置屬性'視圖名'空對象 \t在java.lang.Thread.run(Thread.java:680) – 2011-05-30 18:53:32

0

您能否將render函數的參考傳遞給doResponse函數?

即:

if(condition) { 
    doResponse(request, response, params, this.&render) 
} 

boolean doResponse(request, response, params, renderFn) { 
// Do Stuff 
    renderFn(status: statusCode, contentType: "text/xml", encoding: "ISO-8859-1", text: text) 
// Do post-render stuff 
    return false 
} 
+0

不幸的是,這似乎等同於從doResponse()直接調用render()。我犯了同樣的錯誤。 – Einar 2010-11-04 15:39:38

+0

織補。出於興趣,你能否將錯誤追加到問題文本中? – 2010-11-04 15:50:58

+0

當然。看起來SO剪切了異常文本的最後部分,但它應該足夠了。 – Einar 2010-11-04 15:57:03

0

你可以試試這個解決方案。

變化doResponse到閉合:

def doResponse = { 
     render(status: statusCode, contentType: "text/xml", encoding: "ISO-8859-1", text: text) 
     return false 
} 

調用doResponse(從過濾器關閉):

def doResponseClosure = doResponse.clone() 
doResponseClosure.delegate = delegate 
// if it doesn't work, try adding: doResponseClosure.owner = owner 
return doResponseClosure() 

克隆是因爲併發原因而進行。

我一直在成功地在其他Grails DSL中使用這種方法,如Criteria閉包。

+0

謝謝。這是有效的,但robbberts的解決方案需要的代碼略少。 – Einar 2010-11-05 12:57:48

相關問題