1. 概述
Unirest是Mashape的轻量级HTTP客户端库,除了Java,它还适用于Node.js、.Net、Python、Ruby等。
在开始之前,请注意我们将使用mocky.io来处理所有HTTP请求。
2. Maven设置
首先,我们来添加必要的依赖:
<dependency>
<groupId>com.mashape.unirest</groupId>
<artifactId>unirest-java</artifactId>
<version>1.4.9</version>
</dependency>
此处查看最新版本。
3. 简单请求
让我们发送一个简单的HTTP请求,以了解框架的语义:
@Test
public void shouldReturnStatusOkay() {
HttpResponse<JsonNode> jsonResponse
= Unirest.get("http://www.mocky.io/v2/5a9ce37b3100004f00ab5154")
.header("accept", "application/json").queryString("apiKey", "123")
.asJson();
assertNotNull(jsonResponse.getBody());
assertEquals(200, jsonResponse.getStatus());
}
请注意,该API流式、高效且易于阅读。
我们使用header()和fields() API传递标头和参数。
并且请求在asJson()方法调用上被调用;这里我们还有其他选项,例如asBinary()、asString()和asObject()。
要传递多个标头或字段,我们可以创建一个Map并分别将它们传递给.headers(Map<String, Object> headers)和.fields(Map<String, String> fields):
@Test
public void shouldReturnStatusAccepted() {
Map<String, String> headers = new HashMap<>();
headers.put("accept", "application/json");
headers.put("Authorization", "Bearer 5a9ce37b3100004f00ab5154");
Map<String, Object> fields = new HashMap<>();
fields.put("name", "Sam Tuyucheng");
fields.put("id", "PSP123");
HttpResponse<JsonNode> jsonResponse
= Unirest.put("http://www.mocky.io/v2/5a9ce7853100002a00ab515e")
.headers(headers).fields(fields)
.asJson();
assertNotNull(jsonResponse.getBody());
assertEquals(202, jsonResponse.getStatus());
}
3.1 传递查询参数
要将数据作为查询字符串传递,我们将使用queryString()方法:
HttpResponse<JsonNode> jsonResponse
= Unirest.get("http://www.mocky.io/v2/5a9ce37b3100004f00ab5154")
.queryString("apiKey", "123")
3.2 使用路径参数
为了传递任何URL参数,我们可以使用routeParam()方法:
HttpResponse<JsonNode> jsonResponse
= Unirest.get("http://www.mocky.io/v2/5a9ce37b3100004f00ab5154/{userId}")
.routeParam("userId", "123")
参数占位符名称必须与方法的第一个参数相同。
3.3 带正文的请求
如果我们的请求需要字符串/JSON 主体,我们将使用body()方法传递它:
@Test
public void givenRequestBodyWhenCreatedThenCorrect() {
HttpResponse<JsonNode> jsonResponse
= Unirest.post("http://www.mocky.io/v2/5a9ce7663100006800ab515d")
.body("{\"name\":\"Sam Tuyucheng\", \"city\":\"viena\"}")
.asJson();
assertEquals(201, jsonResponse.getStatus());
}
3.4 对象映射器
为了在请求中使用asObject()或body(),我们需要定义对象映射器。为简单起见,我们将使用Jackson对象映射器。
让我们首先向pom.xml添加以下依赖:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.2</version>
</dependency>
始终使用Maven Central上的最新版本。
现在让我们配置映射器:
Unirest.setObjectMapper(new ObjectMapper() {
com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
public String writeValue(Object value) {
return mapper.writeValueAsString(value);
}
public <T> T readValue(String value, Class<T> valueType) {
return mapper.readValue(value, valueType);
}
});
请注意,setObjectMapper()只能被调用一次,用于设置映射器;一旦设置了映射器实例,它将用于所有请求和响应。
现在让我们使用自定义Article对象测试新功能:
@Test
public void givenArticleWhenCreatedThenCorrect() {
Article article = new Article("ID1213", "Guide to Rest", "tuyucheng");
HttpResponse<JsonNode> jsonResponse
= Unirest.post("http://www.mocky.io/v2/5a9ce7663100006800ab515d")
.body(article)
.asJson();
assertEquals(201, jsonResponse.getStatus());
}
4. 请求方法
与任何HTTP客户端类似,该框架为每个HTTP动词提供了单独的方法:
POST:
Unirest.post("http://www.mocky.io/v2/5a9ce7663100006800ab515d")
PUT:
Unirest.put("http://www.mocky.io/v2/5a9ce7663100006800ab515d")
GET:
Unirest.get("http://www.mocky.io/v2/5a9ce7663100006800ab515d")
DELETE:
Unirest.delete("http://www.mocky.io/v2/5a9ce7663100006800ab515d")
PATCH:
Unirest.patch("http://www.mocky.io/v2/5a9ce7663100006800ab515d")
OPTIONS:
Unirest.options("http://www.mocky.io/v2/5a9ce7663100006800ab515d")
5. 响应方法
一旦我们得到响应,让我们检查状态码和状态消息:
//...
jsonResponse.getStatus()
//...
提取标头:
//...
jsonResponse.getHeaders();
//...
获取响应主体:
//...
jsonResponse.getBody();
jsonResponse.getRawBody();
//...
请注意,getRawBody()返回未解析的响应主体流,而getBody()使用前面部分定义的对象映射器返回已解析的主体。
6. 处理异步请求
Unirest还具有处理异步请求的能力——使用java.util.concurrent.Future和回调方法:
@Test
public void whenAsyncRequestShouldReturnOk() {
Future<HttpResponse<JsonNode>> future = Unirest.post(
"http://www.mocky.io/v2/5a9ce37b3100004f00ab5154?mocky-delay=10000ms")
.header("accept", "application/json")
.asJsonAsync(new Callback<JsonNode>() {
public void failed(UnirestException e) {
// Do something if the request failed
}
public void completed(HttpResponse<JsonNode> response) {
// Do something if the request is successful
}
public void cancelled() {
// Do something if the request is cancelled
}
});
assertEquals(200, future.get().getStatus());
}
com.mashape.unirest.http.async.Callback<T>接口提供了三种方法,failed()、canceled()和completed()。
重写方法以根据响应执行必要的操作。
7. 文件上传
要将文件作为请求的一部分上传或发送,请将java.io.File对象作为名为file的字段传递:
@Test
public void givenFileWhenUploadedThenCorrect() {
HttpResponse<JsonNode> jsonResponse = Unirest.post(
"http://www.mocky.io/v2/5a9ce7663100006800ab515d")
.field("file", new File("/path/to/file"))
.asJson();
assertEquals(201, jsonResponse.getStatus());
}
我们也可以使用ByteStream:
@Test
public void givenByteStreamWhenUploadedThenCorrect() {
try (InputStream inputStream = new FileInputStream(
new File("/path/to/file/artcile.txt"))) {
byte[] bytes = new byte[inputStream.available()];
inputStream.read(bytes);
HttpResponse<JsonNode> jsonResponse = Unirest.post(
"http://www.mocky.io/v2/5a9ce7663100006800ab515d")
.field("file", bytes, "article.txt")
.asJson();
assertEquals(201, jsonResponse.getStatus());
}
}
或者直接使用输入流,在fields()方法中添加ContentType.APPLICATION_OCTET_STREAM作为第二个参数:
@Test
public void givenInputStreamWhenUploadedThenCorrect() {
try (InputStream inputStream = new FileInputStream(
new File("/path/to/file/artcile.txt"))) {
HttpResponse<JsonNode> jsonResponse = Unirest.post(
"http://www.mocky.io/v2/5a9ce7663100006800ab515d")
.field("file", inputStream, ContentType.APPLICATION_OCTET_STREAM, "article.txt").asJson();
assertEquals(201, jsonResponse.getStatus());
}
}
8. Unirest配置
该框架还支持HTTP客户端的典型配置,如连接池、超时、全局标头等。
让我们设置每个路由的连接数和最大连接数:
Unirest.setConcurrency(20, 5);
配置连接和套接字超时:
Unirest.setTimeouts(20000, 15000);
请注意,时间值以毫秒为单位。
现在让我们为所有请求设置HTTP标头:
Unirest.setDefaultHeader("X-app-name", "tuyucheng-unirest");
Unirest.setDefaultHeader("X-request-id", "100004f00ab5");
我们可以随时清除全局标头:
Unirest.clearDefaultHeaders();
在某些时候,我们可能需要通过代理服务器发出请求:
Unirest.setProxy(new HttpHost("localhost", 8080));
需要注意的一个重要方面是正常关闭或退出应用程序,Unirest生成一个后台事件循环来处理操作,我们需要在退出应用程序之前关闭该循环:
Unirest.shutdown();
9. 总结
在本教程中,我们重点介绍了轻量级HTTP客户端框架-Unirest。我们使用了一些简单的示例,既有同步模式,也有异步模式。
最后,我们还使用了一些高级配置-例如连接池、代理设置等。
Post Directory
