Перейти к основному содержимому

Руководство по Google-Http-клиенту

· 7 мин. чтения

1. Обзор

В этой статье мы рассмотрим клиентскую библиотеку Google HTTP для Java , которая представляет собой быструю, хорошо абстрагированную библиотеку для доступа к любым ресурсам через протокол соединения HTTP.

Основными особенностями клиента являются:

  • уровень абстракции HTTP, который позволяет отделить любую низкоуровневую библиотеку
  • быстрые, эффективные и гибкие модели анализа JSON и XML содержимого HTTP-ответа и запроса
  • простые в использовании аннотации и абстракции для сопоставления ресурсов 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. Простой запрос

Давайте начнем с простого запроса GET на страницу GitHub, чтобы продемонстрировать, как 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 обрабатывает фактическое выполнение запроса.

Мы рассмотрим все это и более сложный пример с реальным API, который возвращает формат JSON, в следующих разделах.

4. Подключаемый HTTP-транспорт

В библиотеке есть хорошо абстрагированный класс HttpTransport , который позволяет нам строить поверх него и переходить на базовую низкоуровневую транспортную библиотеку HTTP по выбору :

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

В этом примере мы используем NetHttpTransport , основанный на HttpURLConnection , который можно найти во всех пакетах SDK для Java. Это хороший стартовый выбор, так как он хорошо известен и надежен.

Конечно, может быть случай, когда нам нужна расширенная настройка и, следовательно, потребность в более сложной низкоуровневой библиотеке.

Для таких случаев есть ApacheHttpTransport:

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

ApacheHttpTransport основан на популярном Apache HttpClient , который включает широкий спектр вариантов настройки соединений.

Кроме того, библиотека предоставляет возможность построить низкоуровневую реализацию, что делает ее очень гибкой.

5. Разбор JSON

Клиент Google Http включает еще одну абстракцию для синтаксического анализа JSON. Основным преимуществом этого является взаимозаменяемость выбора библиотеки низкоуровневого синтаксического анализа .

Есть три встроенных варианта, каждый из которых расширяет 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 , чтобы указать поля, которые необходимо проанализировать или сериализовать в 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 . Кроме того, не имеет значения ни видимость полей, ни наличие методов получения или установки.

Мы можем указать значение аннотации @Key , чтобы сопоставить его с правильным ключом JSON.

5.3. ДженерикДжсон

Анализируются только те поля, которые мы объявляем и помечаем как @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 содержит список пользователей, нам нужно предоставить сложный Type , который представляет собой List<User> .

Затем в последней строке мы делаем вызов и анализируем ответ на список нашего класса User .

7. Пользовательские заголовки

Одна вещь, которую мы обычно делаем при выполнении запроса API, — это включение какого-либо пользовательского заголовка или даже модифицированного:

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

Мы делаем это, получая HttpHeaders после того, как мы создали наш запрос, но до его выполнения и добавления необходимых значений.

Имейте в виду, что HTTP-клиент Google включает некоторые заголовки в качестве специальных методов. Например , заголовок User-Agent , если мы попытаемся включить его только с помощью метода set, это вызовет ошибку.

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 , поэтому мы должны включить экземпляр HttpUnsuccessfulResponseHandler в HttpRequest , чтобы активировать его.

9. Ведение журнала

Клиент Google Http использует 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. Заключение

В этом руководстве мы показали клиентскую библиотеку Google HTTP для Java и ее более полезные функции. Их Github содержит больше информации об этом, а также исходный код библиотеки.

Как всегда, полный исходный код этого руководства доступен на GitHub .