从地图动态构造闭包?

时间:2015-12-09 16:29:40

标签: soap groovy closures

我正在尝试制作一个发送SOAP请求和获取响应的通用方法。我正在使用Groovy编程,我正在使用wslite库来帮助我使用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) {
               ...
               }
          }
     }
}

我的问题在于构造请求体的闭包。例如,如果我的方法收到了service AddserviceNamespace http://tempuri.org/parameter地图,请执行以下操作:[intA: x, intB: y]。 ..如何合并所有这些,以便我可以构造这种闭包:

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

我几乎是Groovy的新手,所以不要太苛刻。如果有更好的方法来实现这种通用方法的概念,我很乐意听到它。该概念类似于this。但我宁愿玩Map而不是String。我真的没有使用Grails。简单的Groovy。

1 个答案:

答案 0 :(得分:2)

简而言之,cfrick是正确的:

has_many :jobs, dependent: :destroy

它是如何工作的?

查看其工作原理的简单方法是使用假客户端类进行模拟:

[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的NodeBuilder创建。它只是一种快速的方法来处理传递给response的闭包的原型。

使用这个可测试的代码,我将尝试cfrick建议并验证它是否有效:

Client.send()

请求正文

此外,您可以分解创建请求正文的过程:

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'