Soap 从映射动态构造闭包?

Soap 从映射动态构造闭包?,soap,groovy,closures,Soap,Groovy,Closures,我正在尝试创建一个发送SOAP请求和获取响应的通用方法。我正在使用Groovy编程,我正在使用库来帮助我解决SOAP问题。下面是一个用于发出SOAP请求并获得响应的示例片段: @Grab('com.github.groovy-wslite:groovy-wslite:1.1.2') import wslite.soap.* SOAPClient client = new SOAPClient('http://www.dneonline.com/calculator.asmx') def res

我正在尝试创建一个发送SOAP请求和获取响应的通用方法。我正在使用Groovy编程,我正在使用库来帮助我解决SOAP问题。下面是一个用于发出SOAP请求并获得响应的示例片段:

@Grab('com.github.groovy-wslite:groovy-wslite:1.1.2')
import wslite.soap.*

SOAPClient client = new SOAPClient('http://www.dneonline.com/calculator.asmx')
def response = client.send(SOAPAction: 'http://tempuri.org/Add') {
     body {
          Add(xmlns: 'http://tempuri.org/') {
               intA(x)
               intB(y)
          }
     }
}
一般来说,我的意思是能够动态创建SOAP请求(给定某些信息,如服务/方法名称、方法中包含的参数等)并获得SOAP响应。我是这样想的:

@Grab('com.github.groovy-wslite:groovy-wslite:1.1.2')
import wslite.soap.*

def getResponse(String clientURL, String action, String service, String serviceNamespace, Map parameters, ...) {
     SOAPClient client = new SOAPClient(clientURL)
     def response = client.send(SOAPAction: action) {
          body {
               "$service"(xmlns: serviceNameSpace) {
               ...
               }
          }
     }
}
我的问题在于为请求体构造闭包。例如,在示例中,如果我的方法接收到一个
服务
添加
,一个
服务名称空间
http://tempuri.org/
,以及一个
参数
映射如下:
[intA:x,intB:y]
。。。如何合并所有这些,以便构建此类闭包:

Add(xmlns: 'http://tempuri.org/') {
     intA(x)
     intB(y)
}

我是Groovy的新手,所以不要太苛刻。如果有更好的方法来实现这个通用方法的概念,我很乐意听到。这个概念类似于。但是我宁愿玩
Map
,也不愿玩
String
。我没有使用Grails,真的。只是普通的Groovy。

简而言之,cfrick是正确的:

[intA: x, intB: y].each{fn,arg -> delegate."$fn"(arg) }
它是如何工作的? 了解其工作原理的一个简单方法是使用假客户端类模拟它:

groovy.util.NodeBuilder

class Client {
    def send(String action, Closure closure) {
        closure.delegate = new NodeBuilder()

        closure()
    }
}

def client = new Client()

def response = client.send('http://tempuri.org/Add') {
    body {
        Add(xmlns: 'http://tempuri.org/') {
               intA(1)
               intB(2)
          }
    }   
}

assert response.Add[0].@xmlns == 'http://tempuri.org/'
assert response.Add.intA.text() == '1'
assert response.Add.intB.text() == '2'
在上面的示例中,
响应
对象是由Groovy的。这只是一种快速的方法,可以对传递给
Client.send()
的闭包进行处理

通过这段可测试代码,我将尝试cfrick建议的方法,并验证它是否有效:

def doIt(String action, String service, String serviceNamespace, Map params) {
    def client = new Client()

    client.send(action) {
        body {
            "$service"(xmlns: serviceNamespace) {
                    params.each { method, argument ->
                        delegate."$method"(argument)
                    }
              }
        }   
    }
}

response = doIt('http://tempuri.org/Add', 'Add', 'http://tempuri.org/', [intA: 1, intB: 2])

assert response.Add[0].@xmlns == 'http://tempuri.org/'
assert response.Add.intA.text() == '1'
assert response.Add.intB.text() == '2'
请求主体 此外,您还可以考虑创建请求正文的过程:

def getRequestBody(String service, String serviceNamespace, Map params) {
    { ->
        "$service"(xmlns: serviceNamespace) {
            params.each { method, argument ->
                delegate."$method"(argument)
            }
         }
    }
}

def doIt(String action, String service, String serviceNamespace, Map params) {
    def client = new Client()

    client.send(action) {
        body(getRequestBody(service, serviceNamespace, params))
    }
}

[intA:x,intB:y]每个{fn,arg->delegate.“$fn”(arg)}
都可以吗?现在提问可能有点晚了,但是否可以定义这样一个方法,
getRequestBody()
,它将返回所需的
body{…}
闭包?除此之外,能够在如下位置调用
getRequestBody()
:client.send('http://...“){getRequestBody()}
?如何做到这一点?是的,但不能像
client.send那样调用它http://...“){getRequestBody()}
。相反,您可以编写
getRequestBody
代码,以便像
client.send>一样使用http://...“){body(getRequestBody())}
client.send('http://...,getRequestBody())
。我添加了第一种方法的演示。