A Guide to Google-Http-Client – Google-Http-Client指南

最后修改: 2017年 11月 18日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this article, we’ll have a look at the Google HTTP Client Library for Java, which is a fast, well-abstracted library for accessing any resources via the HTTP connection protocol.

在这篇文章中,我们将看看Google HTTP Client Library for Java,它是一个快速、良好的抽象库,可通过HTTP连接协议访问任何资源。

The main features of the client are:

客户端的主要特点是。

  • an HTTP abstraction layer that lets you decouple any low-level library
  • fast, efficient and flexible JSON and XML parsing models of the HTTP response and request content
  • easy to use annotations and abstractions for HTTP resource mappings

The library can also be used in Java 5 and above, making it a considerable choice for legacy (SE and EE ) projects.

该库也可以在Java 5及以上版本中使用,使其成为遗留(SE和EE)项目的一个相当大的选择。

In this article, we’re going to develop a simple application that will connect to the GitHub API and retrieve users, while covering some of the most interesting features of the library.

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

2. Maven Dependencies

2.Maven的依赖性

To use the library we’ll need the google-http-client dependency:

为了使用该库,我们需要google-http-client依赖。

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

The latest version can be found at Maven Central.

最新版本可在Maven Central找到。

3. Making a Simple Request

3.提出一个简单的要求

Let’s start by making a simple GET request to the GitHub page to showcase how the Google Http Client works out of the box:

让我们先向GitHub页面发出一个简单的GET请求,以展示Google Http Client如何开箱工作。

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

To make the simplest of request we’ll need at least:

要提出最简单的要求,我们至少需要。

  • HttpRequestFactory this is used to build our requests
  • HttpTransport an abstraction of the low-level HTTP transport layer
  • GenericUrl a class that wraps the Url
  • HttpRequest handles the actual execution of the request

We’ll go through all these and a more complex example with an actual API that returns a JSON format in the following sections.

我们将通过所有这些和一个更复杂的例子,用一个实际的API返回一个JSON格式,在下面的章节中。

4. Pluggable HTTP Transport

<4.可插入式HTTP传输

The library has a well-abstracted HttpTransport class that allows us to build on top of it and change to the underlying low-level HTTP transport library of choice:

该库有一个很好的抽象的HttpTransport类,允许我们在它的基础上构建,并改变到所选择的底层HTTP传输库

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

In this example, we’re using the NetHttpTransport, which is based on the HttpURLConnection that is found in all Java SDKs. This is a good starting choice since it’s well-known and reliable.

在这个例子中,我们使用NetHttpTransport,它是基于所有Java SDK中的HttpURLConnection的。这是一个很好的开始选择,因为它是众所周知和可靠的。

Of course, there might be the case where we need some advanced customization, and thus the requirement of a more complex low-level library.

当然,可能会有这样的情况:我们需要一些高级定制,因此需要一个更复杂的底层库。

For this kind of cases, there is the ApacheHttpTransport:

对于这种情况,有一个ApacheHttpTransport:

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

The ApacheHttpTransport is based on the popular Apache HttpClient which includes a wide variety of choices to configure connections.

ApacheHttpTransport基于流行的Apache HttpClient,其中包括多种选择来配置连接。

Additionally, the library provides the option to build your low-level implementation, making it very flexible.

此外,该库提供了建立你的底层实现的选项,使其非常灵活。

5. JSON Parsing

5 JSON解析[/strong]

The Google Http Client includes another abstraction for JSON parsing. A major advantage of this is that the choice of low-level parsing library is interchangeable.

Google Http Client包括另一个用于JSON解析的抽象。这样做的一个主要好处是,底层解析库的选择是可以互换的

There’re three built-in choices, all of which extend JsonFactory, and it also includes the possibility of implementing our own.

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

5.1. Interchangeable Parsing Library

5.1.可互换的解析库

In our example, we’re going to use the Jackson2 implementation, which requires the google-http-client-jackson2 dependency:

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

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

Following this, we can now include the JsonFactory:

在这之后,我们现在可以包括JsonFactory:

public class GitHubExample {

    static HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
    staticJsonFactory JSON_FACTORY = new JacksonFactory();
}

The JacksonFactory is the fastest and most popular library for parsing/serialization operations.

JacksonFactory是解析/序列化操作的最快和最流行的库。

This comes at the cost of the library size (which could be a concern in certain situations). For this reason, Google also provides the GsonFactory, which is an implementation of the Google GSON library, a light-weight JSON parsing library.

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

There is also the possibility of writing our low-level parser implementation.

也有可能编写我们的低级分析器实现。

5.2. The @Key Annotation

5.2.@Key注释

We can use the @Key annotation to indicate fields that need to be parsed from or serialized to JSON:

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

public class User {
 
    @Key
    private String login;
    @Key
    private long id;
    @Key("email")
    private String email;

    // standard getters and setters
}

Here we’re making a User abstraction, which we receive in batch from the GitHub API (we will get to the actual parsing later in this article).

在这里,我们正在制作一个User抽象,我们从GitHub的API中批量接收这个抽象(我们将在本文后面讨论实际解析).

Please note that fields that don’t have the @Key annotation are considered internal and are not parsed from or serialized to JSON. Also, the visibility of the fields does not matter, nor does the existence of the getter or setter methods.

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

We can specify the value of the @Key annotation, to map it to the correct JSON key.

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

5.3. GenericJson

5.3.GenericJson

Only the fields we declare, and mark as @Key are parsed.

只有我们声明并标记为@Key的字段才被解析。

To retain the other content, we can declare our class to extend GenericJson:

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

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

GenericJson implements the Map interface, which means we can use the get and put methods to set/get JSON content in the request/response.

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

6. Making the Call

6.发出呼吁

To connect to an endpoint with the Google Http Client, we’ll need an HttpRequestFactory, which will be configured with our previous abstractions HttpTransport and JsonFactory:

为了用Google Http Client连接到一个端点,我们需要一个HttpRequestFactory,它将被配置为我们之前的抽象HttpTransportJsonFactory:

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));
          });
    }
}

The next thing we’re going to need is a URL to connect to. The library handles this as a class extending GenericUrl on which any field declared is treated as a query parameter:

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

public class GitHubUrl extends GenericUrl {

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

    @Key
    public int per_page;
 
}

Here in our GitHubUrl, we declare the per_page property to indicate how many users we want in a single call to the GitHub API.

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

Let’s continue building our call using the GitHubUrl:

让我们继续使用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);
}

Notice how we specify how many users we’ll need for the API call, and then we build the request with the HttpRequestFactory.

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

Following this, since the GitHub API’s response contains a list of users, we need to provide a complex Type, which is a List<User>.

在这之后,由于GitHub API的响应包含一个用户列表,我们需要提供一个复杂的类型,也就是一个List<User>

Then, on the last line, we make the call and parse the response to a list of our User class.

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

7. Custom Headers

7.自定义页眉

One thing we usually do when making an API request is to include some kind of custom header or even a modified one:

在提出API请求时,我们通常要做的一件事是包括某种自定义头,甚至是修改过的头。

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

We do this by getting the HttpHeaders after we’ve created our request but before executing it and adding the necessary values.

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

Please be aware that the Google Http Client includes some headers as special methods. The User-Agent header for example, if we try to include it with just the set method it would throw an error.

请注意,Google Http Client 包含了一些头文件的特殊方法。例如,User-Agent头,如果我们试图只用set方法来包含它,就会产生一个错误。

8. Exponential Backoff

8.指数反击

Another important feature of the Google Http Client is the possibility to retry requests based on certain status codes and thresholds.

谷歌Http客户端的另一个重要特点是可以根据某些状态代码和阈值重试请求。

We can include our exponential backoff settings right after we’ve created our request object:

我们可以在创建完请求对象后,立即加入我们的指数退避设置。

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

Exponential Backoff is turned off by default in HttpRequest, so we must include an instance of HttpUnsuccessfulResponseHandler to the HttpRequest to activate it.

Exponential Backoff在HttpRequest中默认是关闭的,所以我们必须在HttpUnsuccessfulResponseHandler中包含一个实例以激活它。

9. Logging

9.登录

The Google Http Client uses java.util.logging.Logger for logging HTTP request and response details, including URL, headers, and content.

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

Commonly, logging is managed using a logging.properties file:

通常情况下,日志是使用logging.properties文件来管理的。

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

In our example we use ConsoleHandler, but it’s also possible to choose the FileHandler.

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

The properties file configures the operation of the JDK logging facility. This config file can be specified as a system property:

属性文件配置了 JDK 日志设施的操作。这个配置文件可以作为系统属性来指定。

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

So after setting the file and system property, the library will produce a log like the following:

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

-------------- 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. Conclusion

10.结论

In this tutorial, we’ve shown the Google HTTP Client Library for Java and its more useful features. Their Github contains more information about it as well as the source code of the library.

在本教程中,我们已经展示了用于Java的Google HTTP客户端库及其更多有用的功能。他们的Github包含了更多关于它的信息以及库的源代码。

As always, the full source code of this tutorial is available over on GitHub.

一如既往,本教程的完整源代码可在GitHub上获得