OkHttp для Java: полное руководство с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

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                    

Рекомендаций