OkHttp для Java: HTTP клиент нового поколения
1. Что это и зачем нужна
OkHttp — это современная, эффективная HTTP-библиотека для Java и Android, разработанная компанией Square. Она стала стандартом де-факто для выполнения сетевых запросов в экосистеме Android и активно используется в серверных Java-приложениях. OkHttp предоставляет чистый, fluent API для отправки HTTP-запросов и получения ответов, поддерживая все современные возможности протокола: HTTP/2, WebSockets, GZIP-сжатие, кэширование ответов и автоматическое восстановление соединений при сбоях.
Зачем нужна OkHttp, если есть стандартный java.net.HttpURLConnection? Во-первых, OkHttp значительно проще в использовании — вместо громоздких конструкций с настройкой соединения, вы просто создаёте запрос и выполняете его. Во-вторых, библиотека решает множество проблем «из коробки»: автоматически обрабатывает перенаправления (редиректы), управляет пулом соединений для повторного использования, поддерживает прозрачное сжатие GZIP и умеет кэшировать ответы для экономии трафика. В-третьих, OkHttp лежит в основе таких популярных библиотек, как Retrofit и Picasso, что делает её незаменимой для Android-разработчиков.
OkHttp идеально подходит для любого Java-проекта, где требуется взаимодействие с REST API, загрузка файлов, работа с WebSockets или просто выполнение HTTP-запросов. Благодаря поддержке HTTP/2, библиотека позволяет мультиплексировать запросы через одно соединение, что значительно ускоряет работу с современными серверами. Версия 4.x и выше полностью переписана на Kotlin, но сохраняет полную обратную совместимость с Java-кодом, что делает её доступной для всех Java-разработчиков.
2. Установка
OkHttp распространяется через Maven Central. Для подключения библиотеки к вашему проекту добавьте зависимость в файл build.gradle (для Gradle) или pom.xml (для Maven).
Gradle (Android / Java проект)
dependencies {
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
// Для логирования запросов (опционально)
implementation 'com.squareup.okhttp3:logging-interceptor:4.12.0'
}
Maven
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
</dependency>
Для Java модулей (без Gradle/Maven)
Скачайте JAR-файл с Maven Central и добавьте его в classpath вашего проекта.
Важно: OkHttp 4.x требует Java 8+ или Android API 21+. Для более старых версий используйте OkHttp 3.x.
3. Быстрый старт — минимальный рабочий пример
Самый простой пример — выполнение GET-запроса и вывод тела ответа в консоль. Создайте класс Main.java и скопируйте следующий код:
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import java.io.IOException;
public class Main {
public static void main(String[] args) {
// 1. Создаём HTTP-клиент (обычно один на всё приложение)
OkHttpClient client = new OkHttpClient();
// 2. Строим запрос
Request request = new Request.Builder()
.url("https://api.github.com/users/octocat")
.get()
.build();
// 3. Выполняем запрос синхронно (блокирует поток)
try (Response response = client.newCall(request).execute()) {
if (response.isSuccessful()) {
System.out.println("Ответ: " + response.body().string());
} else {
System.err.println("Ошибка: " + response.code());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Этот код делает GET-запрос к GitHub API, получает информацию о пользователе "octocat" и выводит её в формате JSON. Обратите внимание на использование try-with-resources — это гарантирует, что тело ответа будет закрыто после использования.
4. Основные методы/функции/классы
Ниже представлены 8 ключевых классов и методов OkHttp с подробным описанием и примерами.
4.1. OkHttpClient — основной клиент
Сигнатура: OkHttpClient.Builder() → OkHttpClient build()
Что делает: Создаёт экземпляр HTTP-клиента с настраиваемыми параметрами: таймауты, перехватчики, кэш, прокси и т.д. Рекомендуется создавать один экземпляр на всё приложение и переиспользовать его.
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS) // таймаут подключения
.readTimeout(30, TimeUnit.SECONDS) // таймаут чтения
.writeTimeout(30, TimeUnit.SECONDS) // таймаут записи
.followRedirects(true) // автоматически следовать редиректам
.build();
4.2. Request.Builder — построитель запросов
Сигнатура: Request.Builder() → методы: url(String), get(), post(RequestBody), header(String, String), build()
Что делает: Строит HTTP-запрос с указанием URL, метода, заголовков и тела запроса. Использует паттерн Builder для удобной цепочки вызовов.
Request request = new Request.Builder()
.url("https://httpbin.org/post")
.header("Authorization", "Bearer token123")
.addHeader("Accept", "application/json")
.post(RequestBody.create(
MediaType.parse("application/json"),
"{\"key\":\"value\"}"
))
.build();
4.3. Call — выполняемый запрос
Сигнатура: OkHttpClient.newCall(Request) → Call. Методы: execute() (синхронный), enqueue(Callback) (асинхронный)
Что делает: Представляет собой запрос, который можно выполнить. Поддерживает как синхронное (блокирующее), так и асинхронное выполнение через callback.
// Синхронный вызов
Response response = client.newCall(request).execute();
// Асинхронный вызов
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
System.err.println("Ошибка сети: " + e.getMessage());
}
@Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
System.out.println("Успех: " + response.body().string());
}
}
});
4.4. Response — ответ сервера
Сигнатура: Response — методы: isSuccessful(), code(), message(), headers(), body(), cacheResponse()
Что делает: Содержит результат выполнения запроса: статус-код, заголовки, тело ответа. Тело ответа можно прочитать только один раз, после чего оно закрывается.
try (Response response = client.newCall(request).execute()) {
System.out.println("Код: " + response.code()); // 200
System.out.println("Сообщение: " + response.message()); // "OK"
System.out.println("Заголовки: " + response.headers()); // все заголовки
// Чтение тела ответа
String body = response.body().string(); // один раз!
System.out.println("Тело: " + body);
// Проверка кэшированного ответа
Response cached = response.cacheResponse();
if (cached != null) {
System.out.println("Ответ из кэша");
}
}
4.5. RequestBody — тело запроса
Сигнатура: RequestBody.create(MediaType, String|byte[]|File) или FormBody.Builder()
Что делает: Создаёт тело для POST, PUT, PATCH запросов. Поддерживает различные типы контента: JSON, XML, Form-данные, файлы.
// JSON тело
RequestBody jsonBody = RequestBody.create(
MediaType.parse("application/json; charset=utf-8"),
"{\"login\":\"user\",\"password\":\"pass\"}"
);
// Форма (application/x-www-form-urlencoded)
RequestBody formBody = new FormBody.Builder()
.add("username", "john")
.add("password", "secret")
.build();
// Многокомпонентная форма (multipart/form-data) для загрузки файлов
RequestBody multipartBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file", "photo.jpg",
RequestBody.create(MediaType.parse("image/jpeg"), new File("/path/to/photo.jpg")))
.addFormDataPart("description", "My vacation photo")
.build();
4.6. Headers — работа с заголовками
Сигнатура: Headers.of(String...) или Response.headers(). Методы: get(String), values(String), toMultimap()
Что делает: Управляет HTTP-заголовками запроса и ответа. Позволяет получать значения заголовков, проверять их наличие и работать с повторяющимися заголовками.
// Установка заголовков при создании запроса
Request request = new Request.Builder()
.url("https://api.example.com/data")
.headers(Headers.of(
"Authorization", "Bearer mytoken",
"Accept-Language", "ru-RU,ru;q=0.9",
"X-Custom-Header", "value"
))
.build();
// Чтение заголовков из ответа
try (Response response = client.newCall(request).execute()) {
// Получить один заголовок
String contentType = response.header("Content-Type");
// Получить все значения заголовка (если их несколько)
List<String> cookies = response.headers("Set-Cookie");
// Преобразовать в Map
Map<String, List<String>> allHeaders = response.headers().toMultimap();
}
4.7. Interceptor — перехватчики запросов
Сигнатура: Interceptor — интерфейс с методом Response intercept(Chain chain). Добавляется через OkHttpClient.Builder.addInterceptor() или .addNetworkInterceptor()
Что делает: Позволяет перехватывать и модифицировать запросы и ответы. Используется для логирования, добавления заголовков аутентификации, сжатия, повторных попыток.
// Пример перехватчика для логирования
Interceptor loggingInterceptor = chain -> {
Request original = chain.request();
long startTime = System.nanoTime();
System.out.println("--> " + original.method() + " " + original.url());
Response response = chain.proceed(original);
long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);
System.out.println("<-- " + response.code() + " " + response.message()
+ " (" + elapsedTime + "ms)");
return response;
};
// Пример перехватчика для добавления токена
Interceptor authInterceptor = chain -> {
Request original = chain.request();
Request newRequest = original.newBuilder()
.header("Authorization", "Bearer " + getToken())
.build();
return chain.proceed(newRequest);
};
// Добавление перехватчиков в клиент
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(authInterceptor) // прикладной перехватчик
.addNetworkInterceptor(loggingInterceptor) // сетевой перехватчик
.build();
4.8. Cache — кэширование ответов
Сигнатура: new Cache(File directory, long maxSize)
Что делает: Включает кэширование HTTP-ответов на диске. OkHttp автоматически сохраняет ответы и возвращает их при повторных запросах, если это разрешено заголовками Cache-Control.
// Создание кэша
int cacheSize = 10 * 1024 * 1024; // 10 МБ
File cacheDirectory = new File(System.getProperty("java.io.tmpdir"), "okhttp-cache");
Cache cache = new Cache(cacheDirectory, cacheSize);
// Клиент с кэшем
OkHttpClient client = new OkHttpClient.Builder()
.cache(cache)
.build();
// Первый запрос — будет загружен с сервера
Request request = new Request.Builder()
.url("https://api.github.com/users/octocat")
.build();
try (Response response1 = client.newCall(request).execute()) {
System.out.println("Первый запрос: " + response1.cacheResponse()); // null
System.out.println("Сеть: " + response1.networkResponse()); // не null
}
// Второй запрос — будет взят из кэша (если Cache-Control позволяет)
try (Response response2 = client.newCall(request).execute()) {
System.out.println("Второй запрос: " + response2.cacheResponse()); // не null
System.out.println("Из кэша: " + (response2.cacheResponse() != null));
}
5. Реальный практический пример (100-200 строк кода)
Давайте создадим полноценный класс для работы с REST API GitHub. Он будет получать информацию о пользователе, список его репозиториев и создавать issue в репозитории. Пример демонстрирует синхронные и асинхронные вызовы, обработку ошибок, работу с JSON (через встроенный Gson) и кэширование.
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken Также в библиотеке
Валидация данных в Go: библиотеки, примеры и лучшие практики
OAuth клиент для Go (Golang): полное руководство по библиотеке
Работа с датами в C++: обзор библиотек для манипуляции временем