从 Grails 中的过滤器辅助方法调用 render()

发布于 2024-09-30 11:43:21 字数 1203 浏览 8 评论 0原文

我有如下定义的过滤器。它们在不同的地方运行相同的代码块,因此为了保持干燥,我将该代码重构为一个名为 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 ,编码:ISO-8859-1,文本:...]]

I have filters like the ones defined below. They run the same code block in various places, so to keep it DRY I refactored that code into a method called 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
    }
}

However this has a nasty side effect. It seems that the render() method is only available from within the filters closure. Is there any (neat) way for me to call render() from doResponse()?

Edit: The error I get is:

groovy.lang.MissingMethodException: No signature of method: MyFilters.render() is applicable for argument types: (java.util.LinkedHashMap) values: [[status:500, contentType:text/xml, encoding:ISO-8859-1, text:...]]

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

拒绝两难 2024-10-07 11:43:21

将定义 render(..) 方法的对象传递给 doRespond(..) 方法,并调用 render(..)该对象上的方法。

闭包有一些隐式变量,包括它们引用的所有者父闭包;所以我们可以传递:

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
}

Pass the object that defines the render(..) method to the doRespond(..) method, and invoke the render(..) method on that object.

Closures have some implicit variables, including their owner that refers to the parent closure; so we can pass that:

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

doRespond(..) method:

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
}
幸福还没到 2024-10-07 11:43:21

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

Could you pass a reference to the render function to the doResponse function?

ie:

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

and

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
}
小猫一只 2024-10-07 11:43:21

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

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

You could try this solution.

Change doResponse to a closure:

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

Calling doResponse (from filter closure):

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

The cloning is done because of concurrency reasons.

I've been using this method successfully in other Grails DSLs like Criteria closures.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文