1. Overview
1.概述
Unirest is a lightweight HTTP client library from Mashape. Along with Java, it’s also available for Node.js, .Net, Python, Ruby, etc.
Unirest是Mashape的一个轻量级HTTP客户端库。除了Java,它也可用于Node.js、.Net、Python、Ruby等。
Before we jump in, note that we’ll use mocky.io for all our HTTP requests here.
在我们开始之前,请注意我们将使用mocky.io来处理我们这里的所有HTTP请求。
2. Maven Setup
2.Maven的设置
To get started, let’s add the necessary dependencies first:
为了开始工作,让我们先添加必要的依赖性。
<dependency>
<groupId>com.mashape.unirest</groupId>
<artifactId>unirest-java</artifactId>
<version>1.4.9</version>
</dependency>
Check out the latest version here.
请查看最新版本这里。
3. Simple Requests
3.简单的要求
Let’s send a simple HTTP request, to understand the semantics of the framework:
让我们发送一个简单的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());
}
Notice that the API is fluent, efficient and quite easy to read.
请注意,该API是流畅的、高效的,而且相当容易阅读。
We’re passing headers and parameters with the header() and fields() APIs.
我们用header() 和fields() API来传递头和参数。
And the request gets invoked on the asJson() method call; we also have other options here, such as asBinary(), asString() and asObject().
而请求被调用的asJson()方法;我们在这里还有其他选项,比如asBinary()、asString()和asObject()。
To pass multiple headers or fields, we can create a map and pass them to .headers(Map<String, Object> headers) and .fields(Map<String, String> fields) respectively:
要传递多个头或字段,我们可以创建一个地图,并分别传递给.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 Baeldung");
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. Passing Query Params
3.1.传递查询参数
To pass data as a query String, we’ll use the queryString() method:
为了将数据作为查询字符串传递,我们将使用queryString() 方法。
HttpResponse<JsonNode> jsonResponse
= Unirest.get("http://www.mocky.io/v2/5a9ce37b3100004f00ab5154")
.queryString("apiKey", "123")
3.2. Using Path Params
3.2.使用路径参数
For passing any URL parameters, we can use the routeParam() method:
对于传递任何URL参数,我们可以使用routeParam()方法。
HttpResponse<JsonNode> jsonResponse
= Unirest.get("http://www.mocky.io/v2/5a9ce37b3100004f00ab5154/{userId}")
.routeParam("userId", "123")
The parameter placeholder name must be same as the first argument to the method.
参数的占位符名称必须与方法的第一个参数相同。
3.3. Requests With Body
3.3.有主体的请求
If our request requires a string/JSON body, we pass it using the body() method:
如果我们的请求需要一个字符串/JSON体,我们使用body()方法来传递它。
@Test
public void givenRequestBodyWhenCreatedThenCorrect() {
HttpResponse<JsonNode> jsonResponse
= Unirest.post("http://www.mocky.io/v2/5a9ce7663100006800ab515d")
.body("{\"name\":\"Sam Baeldung\", \"city\":\"viena\"}")
.asJson();
assertEquals(201, jsonResponse.getStatus());
}
3.4. Object Mapper
3.4.对象映射器
In order to use the asObject() or body() in the request, we need to define our object mapper. For simplicity, we’ll use the Jackson object mapper.
为了在请求中使用asObject()或body(),我们需要定义我们的对象映射器。为了简单起见,我们将使用Jackson对象映射器。
Let’s first add the following dependencies to pom.xml:
让我们首先将以下依赖项添加到pom.xml。
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.12.4</version>
</dependency>
Always use the latest version over on Maven Central.
始终使用最新的版本超过在Maven Central。
Now let’s configure our mapper:
现在让我们来配置我们的映射器。
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);
}
});
Note that setObjectMapper() should only be called once, for setting the mapper; once the mapper instance is set, it will be used for all request and responses.
注意,setObjectMapper()只应被调用一次,用于设置映射器;一旦映射器实例被设置,它将被用于所有请求和响应。
Let’s now test the new functionality using a custom Article object:
现在让我们使用一个自定义的Article对象来测试这个新功能。
@Test
public void givenArticleWhenCreatedThenCorrect() {
Article article
= new Article("ID1213", "Guide to Rest", "baeldung");
HttpResponse<JsonNode> jsonResponse
= Unirest.post("http://www.mocky.io/v2/5a9ce7663100006800ab515d")
.body(article)
.asJson();
assertEquals(201, jsonResponse.getStatus());
}
4. Request Methods
4.请求方法
Similar to any HTTP client, the framework provides separate methods for each HTTP verb:
与任何HTTP客户端类似,该框架为每个HTTP动词提供单独的方法。
POST:
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:
DELETE。
Unirest.delete("http://www.mocky.io/v2/5a9ce7663100006800ab515d")
PATCH:
PATCH:
Unirest.patch("http://www.mocky.io/v2/5a9ce7663100006800ab515d")
OPTIONS:
选择。
Unirest.options("http://www.mocky.io/v2/5a9ce7663100006800ab515d")
5. Response Methods
5.应对方法
Once we get the response, let check the status code and status message:
一旦我们得到响应,让我们检查状态代码和状态信息。
//...
jsonResponse.getStatus()
//...
Extract the headers:
提取头文件。
//...
jsonResponse.getHeaders();
//...
Get the response body:
获取响应主体。
//...
jsonResponse.getBody();
jsonResponse.getRawBody();
//...
Notice that, the getRawBody(), returns a stream of the unparsed response body, whereas the getBody() returns the parsed body, using the object mapper defined in the earlier section.
请注意,getRawBody(),返回一个未经解析的响应体流,而getBody()则使用前面章节中定义的对象映射器返回已解析的响应体。
6. Handling Asynchronous Requests
6.处理异步请求
Unirest also has the capability to handle asynchronous requests – using java.util.concurrent.Future and callback methods:
Unirest也有处理异步请求的能力–使用java.util.concurrent.Future和回调方法。
@Test
public void whenAysncRequestShouldReturnOk() {
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());
}
The com.mashape.unirest.http.async.Callback<T> interface provides three methods, failed(), cancelled() and completed().
com.mashape.unirest.http.async.Callback<T>接口提供了三个方法,failed(), cancelled()和 completed()。
Override the methods to perform the necessary operations depending on the response.
覆盖这些方法,根据响应情况执行必要的操作。
7. File Uploads
7.文件上传
To upload or send a file as a part of the request, pass a java.io.File object as a field with name file:
要上传或发送一个文件作为请求的一部分,需要传递一个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());
}
We can also use ByteStream:
我们也可以使用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());
}
}
Or use the input stream directly, adding the ContentType.APPLICATION_OCTET_STREAM as the second argument in the fields() method:
或者直接使用输入流,将ContentType.APPLICATION_OCTET_STREAM作为fields() 方法的第二个参数。
@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 Configurations
8.Unirest配置
The framework also supports typical configurations of an HTTP client like connection pooling, timeouts, global headers etc.
该框架还支持HTTP客户端的典型配置,如连接池、超时、全局头信息等。
Let’s set the number of connections and number maximum connections per route:
让我们来设置每个路由的连接数和最大连接数。
Unirest.setConcurrency(20, 5);
Configure connection and socket timeouts :
配置连接和套接字的超时。
Unirest.setTimeouts(20000, 15000);
Note that the time values are in milliseconds.
注意,时间值的单位是毫秒。
Now let’s set HTTP headers for all our requests:
现在让我们为我们所有的请求设置HTTP头。
Unirest.setDefaultHeader("X-app-name", "baeldung-unirest");
Unirest.setDefaultHeader("X-request-id", "100004f00ab5");
We can clear the global headers anytime:
我们可以随时清除全局标题。
Unirest.clearDefaultHeaders();
At some point, we might need to make requests through a proxy server:
在某些时候,我们可能需要通过代理服务器发出请求。
Unirest.setProxy(new HttpHost("localhost", 8080));
One important aspect to be aware of is closing or exiting the application gracefully. Unirest spawns a background event loop to handle the operations, we need to shut down that loop before exiting our application:
需要注意的一个重要方面是优雅地关闭或退出应用程序。Unirest产生了一个后台事件循环来处理操作,我们需要在退出我们的应用程序之前关闭该循环。
Unirest.shutdown();
9. Conclusion
9.结论
In this tutorial, we focused on the lightweight HTTP client framework – Unirest. We worked with some simple examples, both in a synchronous but also async modes.
在本教程中,我们专注于轻量级的HTTP客户端框架 – Unirest。我们使用了一些简单的例子,既有同步模式也有异步模式。
Finally, we also used several advanced configurations – such as connection pooling, proxy settings etc.
最后,我们还使用了几个高级配置–如连接池、代理设置等。
As usual, the source code is available over on GitHub.
像往常一样,源代码可在GitHub上获得。