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的动态方法没有通过传递的闭包正确连接,或类似的东西
答案 0 :(得分:3)
看起来正在发生的事情是关闭代表迷路了。代表是Groovy闭包工作的重要组成部分。每个闭包都有一个与之关联的委托对象,并且可以在委托上调用闭包内调用的任何方法。确切的顺序可以使用Closure.setResolveStrategy进行自定义,但默认情况下首先尝试对所有者(声明闭包的位置)的方法,然后是委托。您始终可以在delegate
的闭包中显式引用该委托。
代表是提供setHeaders()
等神奇动态方法的主要机制。当HttpBuilder调用你传入的闭包时,它会设置显式闭包的委托,但会跳过stmts()
。您需要做的就是将代理传递给stmts()
。尝试这样的事情:
def withMyRest(Closure stmts) {
withRest(uri: serverBaseURL) {
headers = requestHeaders
stmts.delegate = delegate
stmts()
}
}