Unirest指南

2025/03/30

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。我们使用了一些简单的示例,既有同步模式,也有异步模式。

最后,我们还使用了一些高级配置-例如连接池、代理设置等。

Show Disqus Comments

Post Directory

扫码关注公众号:Taketoday
发送 290992
即可立即永久解锁本站全部文章