在Groovy中Web服务简介
1. 概述
如今,我们看到了一系列通过 Web 应用程序公开数据的方法。
通常,应用程序使用SOAP 或REST 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看起来非常方便,并且使代码更简洁。
让我们使用JsonSlurper将String响应解析为 JSON:
JsonSlurper jsonSlurper = new JsonSlurper()
assert jsonSlurper.parseText(text)?.json.param1 == "This is request parameter."
3. RSS 和 Atom 提要
RSS 和Atom 提要是通过网络公开新闻、博客和技术论坛等内容的常用方法。
此外,这两个提要都是 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"