【问题标题】:Calling render() from a filter helper method in Grails从 Grails 中的过滤器辅助方法调用 render()
【发布时间】:2010-11-04 15:09:22
【问题描述】:

我有如下定义的过滤器。他们在不同的地方运行相同的代码块,所以为了保持干爽,我将代码重构为一个名为 doResponse() 的方法。

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() 方法只能在过滤器闭包中使用。我有什么(整洁的)方法可以从 doResponse() 调用 render() 吗?

编辑:我得到的错误是:

groovy.lang.MissingMethodException: 没有方法签名: MyFilters.render() 适用于参数类型: (java.util.LinkedHashMap) 值: [[status:500, contentType:text/xml, encoding:ISO- 8859-1,文本:...]]

【问题讨论】:

    标签: grails groovy filter dry


    【解决方案1】:

    将定义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
    }
    

    【讨论】:

    • 嗨,我尝试这样做,但得到:java.lang.NullPointerException: Cannot set property 'viewName' on null object at java.lang.Thread.run(Thread.java:680)跨度>
    【解决方案2】:

    能否将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
    }
    

    【讨论】:

    • 不幸的是,这似乎等同于直接从 doResponse() 调用 render()。我得到同样的错误。
    • 该死。出于兴趣,您能否将收到的错误附加到问题文本中?
    • 当然。似乎 SO 剪断了异常文本的最后部分,但应该足够了。
    • 所以当您尝试上面的代码时,您会得到完全相同的错误吗?还是改为:No signature of method: MyFilters.renderFn()
    • 一模一样,还是在render()上报错,而不是renderFn()
    【解决方案3】:

    你可以试试这个解决方案。

    将 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 闭包)中成功使用了这种方法。

    【讨论】:

    • 谢谢。这可行,但 robbberts 的解决方案需要的代码略少。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-03
    • 2012-02-13
    • 2020-01-27
    • 1970-01-01
    相关资源
    最近更新 更多