为什么我不能用自己的方法包装withRest()并在其中运行闭包?

时间:2011-12-20 17:22:53

标签: groovy griffon httpbuilder

Griffon的HTTPBuilder插件非常棒,它可以很好地简化我的服务器调用。但唯一的问题是,我不想在整个地方不断重复相同的设置代码。

我想要做的是使用相同的连接设置包装一组服务器调用和其他代码,以便我只将它放在一个地方。

举个例子,这就是我所拥有的:

def persistCurrentSession() {
    withRest(uri: serverBaseURL) {
        headers = requestHeaders

        post(path: "${sessionBaseURL}${currentSession.id}",
                body: currentSession,
                requestContentType: groovyx.net.http.ContentType.JSON)
    }
}

def refreshCurrentSession() {
    withRest(uri: serverBaseURL) {
        headers = requestHeaders

        currentSession = get(path: "${sessionBaseURL}${currentSession.id}").responseData.sessionInstance
    }
}

这就是我想要做的事情:

def persistCurrentSession() {
    withMyRest {
        post(path: "${sessionBaseURL}${currentSession.id}",
                body: currentSession,
                requestContentType: groovyx.net.http.ContentType.JSON)
    }
}

def refreshCurrentSession() {
    withMyRest {
        currentSession = get(path: "${sessionBaseURL}${currentSession.id}").responseData.sessionInstance
    }
}

def withMyRest(Closure stmts) {
    withRest(uri: serverBaseURL) {
        headers = requestHeaders
        stmts()
    }
}

根据我对Groovy和闭包的了解,这应该是一个伟大的用于闭包,因为它删除了常见的"设置/拆除资源"代码到一个地方,并允许焦点在服务器调用的主要部分。

问题在于,似乎没有正确添加动态方法,因为当我按照我想要的方式运行代码时,MissingMethodException会在{{1}时被抛出被调用:

stmts()

我确信有更好的方法可以做我想要做的事情,但即便如此,我想我应该做什么工作。我对Groovy还是一个新手,但是我已经多次查看了范围规则,我能想到的是HTTPBuilder的动态方法没有通过传递的闭包正确连接,或类似的东西

1 个答案:

答案 0 :(得分:3)

看起来正在发生的事情是关闭代表迷路了。代表是Groovy闭包工作的重要组成部分。每个闭包都有一个与之关联的委托对象,并且可以在委托上调用闭包内调用的任何方法。确切的顺序可以使用Closure.setResolveStrategy进行自定义,但默认情况下首先尝试对所有者(声明闭包的位置)的方法,然后是委托。您始终可以在delegate的闭包中显式引用该委托。

代表是提供setHeaders()等神奇动态方法的主要机制。当HttpBuilder调用你传入的闭包时,它会设置显式闭包的委托,但会跳过stmts()。您需要做的就是将代理传递给stmts()。尝试这样的事情:

def withMyRest(Closure stmts) {
    withRest(uri: serverBaseURL) {
        headers = requestHeaders
        stmts.delegate = delegate
        stmts()
    }
}