Google Http Client指南

2025/03/30

1. 概述

在本文中,我们将了解Java版GoogleHTTP客户端库,这是一个快速、抽象良好的库,可用于通过HTTP连接协议访问任何资源。

该客户端的主要特点是:

  • 一个HTTP抽象层,可让你解耦任何低级库
  • 快速、高效、灵活的HTTP响应和请求内容的JSON和XML解析模型
  • 易于使用HTTP资源映射的注解和抽象

该库还可以在Java 5及更高版本中使用,这使其成为传统(SE和EE)项目的重要选择。

在本文中,我们将开发一个简单的应用程序,它将连接到GitHub API并检索用户,同时介绍该库的一些最有趣的功能。

2. Maven依赖

要使用该库,我们需要google-http-client依赖:

<dependency>
    <groupId>com.google.http-client</groupId>
    <artifactId>google-http-client</artifactId>
    <version>1.23.0</version>
</dependency>

最新版本可以在Maven Central找到。

3. 发送简单请求

让我们首先向GitHub页面发出一个简单的GET请求,以展示Google HTTP Client的开箱即用方式:

HttpRequestFactory requestFactory
    = new NetHttpTransport().createRequestFactory();
HttpRequest request = requestFactory.buildGetRequest(new GenericUrl("https://github.com"));
String rawResponse = request.execute().parseAsString()

为了发出最简单的请求,我们至少需要:

  • HttpRequestFactory:用于构建我们的请求
  • HttpTransport:是低级HTTP传输层的抽象
  • GenericUrl:包装URL的类
  • HttpRequest:处理请求的实际执行

在以下章节中,我们将介绍所有这些内容,以及一个返回JSON格式的实际API的更复杂示例。

4. 可插拔HTTP传输

该库有一个良好抽象的HttpTransport类,允许我们在此基础上构建并更改为所选的底层低级HTTP传输库

public class GitHubExample {
    static HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
}

在本例中,我们使用NetHttpTransport,它基于所有Java SDK中都有的HttpURLConnection。这是一个不错的入门选择,因为它广为人知且可靠。

当然,在某些情况下我们可能需要一些高级定制,因此需要更复杂的低级库。

对于这种情况,有ApacheHttpTransport:

public class GitHubExample {
    static HttpTransport HTTP_TRANSPORT = new ApacheHttpTransport();
}

ApacheHttpTransport基于流行的Apache HttpClient,它包含多种配置连接的选择。

此外,该库还提供了构建低级实现的选项,使其非常灵活。

5. JSON解析

Google HTTP Client包含另一个JSON解析抽象,这样做的一个主要优点是低级解析库的选择是可互换的。

有3个内置选择,它们都扩展了JsonFactory,并且还包括我们自己实现的可能性。

5.1 可互换解析库

在我们的示例中,我们将使用Jackson2实现,它需要google-http-client-jackson2依赖:

<dependency>
    <groupId>com.google.http-client</groupId>
    <artifactId>google-http-client-jackson2</artifactId>
    <version>1.23.0</version>
</dependency>

接下来,我们现在可以包含JsonFactory:

public class GitHubExample {
    static HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
    staticJsonFactory JSON_FACTORY = new JacksonFactory();
}

JacksonFactory是用于解析/序列化操作的最快和最受欢迎的库

这是以牺牲库大小为代价的(在某些情况下这可能是一个问题)。出于这个原因,Google还提供了GsonFactory,它是Google GSON库(一个轻量级JSON解析库)的一个实现。

我们也可以编写自己的低级解析器实现。

5.2 @Key注解

我们可以使用@Key注解来指示需要从JSON解析或序列化为JSON的字段:

public class User {

    @Key
    private String login;
    @Key
    private long id;
    @Key("email")
    private String email;

    // standard getters and setters
}

在这里,我们创建一个User抽象,我们从GitHub API批量接收它(我们将在本文后面进行实际的解析)。

请注意,没有@Key注解的字段被视为内部字段,不会从JSON解析或序列化为JSON。此外,字段的可见性并不重要,Getter或Setter方法的存在性也不重要。

我们可以指定@Key注解的值,将其映射到正确的JSON键。

5.3 GenericJson

仅解析我们声明并标记为@Key的字段。

为了保留其他内容,我们可以声明我们的类来扩展GenericJson:

public class User extends GenericJson {
    //...
}

GenericJson实现了Map接口,这意味着我们可以使用get和put方法来设置/获取请求/响应中的JSON内容

6. 发送调用

要使用Google HTTP Client连接到端点,我们需要一个HttpRequestFactory,它将使用我们之前的抽象HttpTransport和JsonFactory进行配置:

public class GitHubExample {

    static HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
    static JsonFactory JSON_FACTORY = new JacksonFactory();

    private static void run() throws Exception {
        HttpRequestFactory requestFactory
                = HTTP_TRANSPORT.createRequestFactory(
                (HttpRequest request) -> {
                    request.setParser(new JsonObjectParser(JSON_FACTORY));
                });
    }
}

接下来我们需要一个要连接的URL,该库将其作为扩展GenericUrl的类来处理,其中声明的任何字段都被视为查询参数:

public class GitHubUrl extends GenericUrl {

    public GitHubUrl(String encodedUrl) {
        super(encodedUrl);
    }

    @Key
    public int per_page;
}

在我们的GitHubUrl中,我们声明了per_page属性来指示我们希望在一次调用GitHub API时有多少个用户。

让我们继续使用GitHubUrl构建我们的调用:

private static void run() throws Exception {
    HttpRequestFactory requestFactory
            = HTTP_TRANSPORT.createRequestFactory(
            (HttpRequest request) -> {
                request.setParser(new JsonObjectParser(JSON_FACTORY));
            });
    GitHubUrl url = new GitHubUrl("https://api.github.com/users");
    url.per_page = 10;
    HttpRequest request = requestFactory.buildGetRequest(url);
    Type type = new TypeToken<List<User>>() {}.getType();
    List<User> users = (List<User>)request
            .execute()
            .parseAs(type);
}

请注意我们如何指定API调用需要多少个用户,然后我们使用HttpRequestFactory构建请求。

接下来,由于GitHub API的响应包含用户列表,我们需要提供一个复杂的类型,即List<User>。

然后,在最后一行,我们进行调用并将响应解析为我们的用户类列表。

7. 自定义标头

在发出API请求时,我们通常会做的一件事是包含某种自定义标头,甚至是修改后的标头:

HttpHeaders headers = request.getHeaders();
headers.setUserAgent("Tuyucheng Client");
headers.set("Time-Zone", "Europe/Amsterdam");

我们通过在创建请求之后但在执行请求并添加必要的值之前获取HttpHeaders来实现这一点。

请注意,Google HTTP Client包含一些标头作为特殊方法。例如,如果我们尝试仅使用set方法包含User-Agent标头,则会引发错误。

8. 指数退避

Google HTTP Client的另一个重要功能是可以根据某些状态码和阈值重试请求。

我们可以在创建请求对象之后立即包含指数退避设置:

ExponentialBackOff backoff = new ExponentialBackOff.Builder()
    .setInitialIntervalMillis(500)
    .setMaxElapsedTimeMillis(900000)
    .setMaxIntervalMillis(6000)
    .setMultiplier(1.5)
    .setRandomizationFactor(0.5)
    .build();
request.setUnsuccessfulResponseHandler(new HttpBackOffUnsuccessfulResponseHandler(backoff));

HttpRequest中的指数退避默认是关闭的,所以我们必须在HttpRequest中包含一个HttpUnsuccessfulResponseHandler实例来激活它。

9. 日志记录

Google HTTP Client使用java.util.logging.Logger记录HTTP请求和响应详细信息,包括URL、标头和内容。

通常,使用logging.properties文件来管理日志:

handlers = java.util.logging.ConsoleHandler
java.util.logging.ConsoleHandler.level = ALL
com.google.api.client.http.level = ALL

在我们的示例中,我们使用ConsoleHandler,但也可以选择FileHandler。

属性文件配置JDK日志记录工具的操作,此配置文件可以指定为系统属性:

-Djava.util.logging.config.file=logging.properties

因此,在设置文件和系统属性后,该库将产生如下日志:

-------------- REQUEST  --------------
GET https://api.github.com/users?page=1&per_page=10
Accept-Encoding: gzip
User-Agent: Google-HTTP-Java-Client/1.23.0 (gzip)

Nov 12, 2017 6:43:15 PM com.google.api.client.http.HttpRequest execute
curl -v --compressed -H 'Accept-Encoding: gzip' -H 'User-Agent: Google-HTTP-Java-Client/1.23.0 (gzip)' -- 'https://api.github.com/users?page=1&per_page=10'
Nov 12, 2017 6:43:16 PM com.google.api.client.http.HttpResponse 
-------------- RESPONSE --------------
HTTP/1.1 200 OK
Status: 200 OK
Transfer-Encoding: chunked
Server: GitHub.com
Access-Control-Allow-Origin: *
...
Link: <https://api.github.com/users?page=1&per_page=10&since=19>; rel="next", <https://api.github.com/users{?since}>; rel="first"
X-GitHub-Request-Id: 8D6A:1B54F:3377D97:3E37B36:5A08DC93
Content-Type: application/json; charset=utf-8
...

10. 总结

在本教程中,我们展示了Java版Google HTTP客户端库及其更多有用功能。

Show Disqus Comments

Post Directory

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