Contents

在Groovy中Web服务简介

1. 概述

如今,我们看到了一系列通过 Web 应用程序公开数据的方法。

通常,应用程序使用SOAPREST Web 服务来公开其 API。但是,也需要考虑 RSS 和 Atom 等流协议。

在这个快速教程中,我们将探索一些在Groovy 中为这些协议中的每一个使用 Web 服务的便捷方法。

2. 执行 HTTP 请求

首先,让我们使用URL 类执行一个简单的 HTTP GET 请求。我们将在探索期间使用Postman Echo API

首先,我们将调用URL类的openConnection方法,然后将requestMethod设置为 GET:

def postmanGet = new URL('https://postman-echo.com/get')
def getConnection = postmanGet.openConnection()
getConnection.requestMethod = 'GET'
assert getConnection.responseCode == 200

同样,我们可以通过将requestMethod设置为 POST 来发出 POST 请求:

def postmanPost = new URL('https://postman-echo.com/post')
def postConnection = postmanPost.openConnection()
postConnection.requestMethod = 'POST'
assert postConnection.responseCode == 200

此外,我们可以使用outputStream.withWriter 将参数传递给 POST 请求:

def form = "param1=This is request parameter."
postConnection.doOutput = true
def text
postConnection.with {
    outputStream.withWriter { outputStreamWriter ->
        outputStreamWriter << form
    }
    text = content.text
}
assert postConnection.responseCode == 200

在这里,带有闭包的 Groovy看起来非常方便,并且使代码更简洁。

让我们使用JsonSlurperString响应解析为 JSON:

JsonSlurper jsonSlurper = new JsonSlurper()
assert jsonSlurper.parseText(text)?.json.param1 == "This is request parameter."

3. RSS 和 Atom 提要

RSSAtom 提要是通过网络公开新闻、博客和技术论坛等内容的常用方法。

此外,这两个提要都是 XML 格式的。因此,我们可以使用 Groovy 的XMLParser 类来解析内容。

让我们利用他们的 RSS 提要阅读一些来自Google 新闻 的头条新闻:

def rssFeed = new XmlParser()
    .parse("https://news.google.com/rss?hl=en-US&gl=US&ceid=US:en")
def stories = []
(0..4).each {
    def item = rssFeed.channel.item.get(it)
    stories << item.title.text()
}
assert stories.size() == 5

同样,我们可以阅读 Atom 提要。但是,由于两种协议的规范不同,我们将在 Atom 提要中以不同的方式访问内容:

def atomFeed = new XmlParser()
    .parse("https://news.google.com/atom?hl=en-US&gl=US&ceid=US:en")
def stories = []
(0..4).each {
    def entry = atomFeed.entry.get(it)
    stories << entry.title.text()
}
assert stories.size() == 5

此外,我们了解 Groovy 支持 Groovy 中鼓励的所有 Java 库。因此,我们当然可以使用Rome API 来读取 RSS 提要。

4. SOAP 请求和响应

SOAP 是应用程序用来在 Web 上公开其服务的最流行的 Web 服务协议之一。

我们将使用groovy-wslite 库来使用 SOAP API。让我们将其最新的依赖 项添加到我们的pom.xml中:

<dependency>
    <groupId>com.github.groovy-wslite</groupId>
    <artifactId>groovy-wslite</artifactId>
    <version>1.1.3</version>
</dependency>

或者,我们可以使用 Gradle 添加最新的依赖项:

compile group: 'com.github.groovy-wslite', name: 'groovy-wslite', version: '1.1.3'

或者,如果我们想编写一个 Groovy 脚本。我们可以使用*@Grab*直接添加它:

@Grab(group='com.github.groovy-wslite', module='groovy-wslite', version='1.1.3')

groovy-wslite 库提供了SOAPClient类来与 SOAP API 进行通信。同时,它有SOAPMessageBuilder类来创建请求消息。

让我们使用SOAPClient使用数字转换 SOAP 服务

def url = "http://www.dataaccess.com/webservicesserver/numberconversion.wso"
def soapClient = new SOAPClient(url)
def message = new SOAPMessageBuilder().build({
    body {
        NumberToWords(xmlns: "http://www.dataaccess.com/webservicesserver/") {
            ubiNum(123)
        }
    }
})
def response = soapClient.send(message.toString());
def words = response.NumberToWordsResponse
assert words == "one hundred and twenty three "

5. REST 请求和响应

REST 是另一种用于创建 Web 服务的流行架构风格。此外,API 是基于 GET、POST、PUT 和 DELETE 等 HTTP 方法公开的。

5.1. GET

我们将使用已经讨论过的 groovy-wslite 库来使用 REST API。它为无障碍通信提供了RESTClient类。

让我们向已经讨论过的 Postman API 发出 GET 请求:

RESTClient client = new RESTClient("https://postman-echo.com")
def path = "/get"
def response
try {
    response = client.get(path: path)
    assert response.statusCode = 200
    assert response.json?.headers?.host == "postman-echo.com"
} catch (RESTClientException e) {
    assert e?.response?.statusCode != 200
}

5.2. POST

现在,让我们向 Postman API 发出 POST 请求。同时,我们将表单参数作为 JSON 传递:

client.defaultAcceptHeader = ContentType.JSON
def path = "/post"
def params = ["foo":1,"bar":2]
def response = client.post(path: path) {
    type ContentType.JSON
    json params
}
assert response.json?.data == params

在这里,我们将 JSON 设置为默认的接受标头。

6. Web服务的认证

随着越来越多的 Web 服务和应用程序相互通信,建议使用安全的 Web 服务。

因此,HTTPS 与 Basic Auth 和 OAuth 等身份验证机制的结合非常重要

因此,应用程序在使用 Web 服务 API 时必须对自身进行身份验证。

6.1. 基本认证

我们可以使用已经讨论过的RESTClient类。让我们使用带有凭据的HTTPBasicAuthorization类来执行基本身份验证:

def path = "/basic-auth"
client.authorization = new HTTPBasicAuthorization("postman", "password")
response = client.get(path: path)
assert response.statusCode == 200
assert response.json?.authenticated == true

或者,我们可以直接在headers参数中传递凭据(Base64 编码) :

def response = client
.get(path: path, headers: ["Authorization": "Basic cG9zdG1hbjpwYXNzd29yZA=="])

6.2. OAuth 1.0

类似地,我们可以发出 OAuth 1.0 请求,传递 auth 参数,如消费者密钥和消费者秘密。

但是,由于我们没有对 OAuth 1.0 的内置支持,就像我们对其他机制所做的那样,我们必须自己完成这项工作:

def path = "/oauth1"
def params = [oauth_consumer_key: "RKCGzna7bv9YD57c", 
    oauth_signature_method: "HMAC-SHA1", 
    oauth_timestamp:1567089944, oauth_nonce: "URT7v4", oauth_version: 1.0, 
    oauth_signature: 'RGgR/ktDmclkM0ISWaFzebtlO0A=']
def response = new RESTClient("https://postman-echo.com")
    .get(path: path, query: params)
assert response.statusCode == 200
assert response.statusMessage == "OK"
assert response.json.status == "pass"