HTTP клиент на Java: делаем запросы правильно от А до Я

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

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

Начать курс

Введение: зачем нужен HTTP клиент в Java?

Современная разработка на Java редко обходится без взаимодействия с внешними сервисами. Будь то отправка данных на сервер, получение информации от REST API или интеграция с облачными платформами — везде требуется HTTP клиент. В Java существует несколько способов выполнить HTTP-запрос, и важно выбрать правильный подход.

Долгое время стандартным инструментом была библиотека java.net.HttpURLConnection, но с выходом Java 11 появился новый, более удобный модуль java.net.http. В этой статье мы разберем все этапы работы с HTTP клиентом на Java: от простых GET-запросов до отправки JSON и обработки ошибок.

Статья ориентирована на разработчиков, которые уже знакомы с основами Java, но хотят систематизировать знания о сетевых запросах. Мы будем использовать встроенный HttpClient из Java 11+, так как это современный и рекомендуемый подход.

1. Основы HTTP клиента: создание и настройка

Прежде чем отправлять запросы, нужно создать экземпляр HttpClient. Это центральный объект, через который выполняются все HTTP-операции. Рассмотрим базовую конфигурацию.

Создание клиента

Самый простой способ — использовать статический метод newHttpClient():

import java.net.http.HttpClient;

HttpClient client = HttpClient.newHttpClient();

Однако для реальных проектов часто требуется настройка таймаутов, версии протокола или прокси. Вот пример расширенной конфигурации:

import java.net.http.HttpClient;
import java.time.Duration;

HttpClient client = HttpClient.newBuilder()
    .version(HttpClient.Version.HTTP_2) // используем HTTP/2
    .connectTimeout(Duration.ofSeconds(10)) // таймаут подключения
    .followRedirects(HttpClient.Redirect.NORMAL) // автоматическое следование редиректам
    .build();

Важные параметры настройки

  • version — выбор между HTTP/1.1 и HTTP/2 (по умолчанию HTTP/2, если сервер поддерживает)
  • connectTimeout — максимальное время ожидания соединения
  • followRedirects — политика обработки редиректов (NEVER, ALWAYS, NORMAL)
  • proxy — настройка прокси-сервера (если требуется)

Обратите внимание: один экземпляр HttpClient можно использовать для множества запросов. Он является потокобезопасным, поэтому его можно создать один раз и переиспользовать во всем приложении.

2. Создание и отправка HTTP запросов

Теперь перейдем к главному — формированию запросов. В Java 11+ для этого используется класс HttpRequest. Рассмотрим основные типы запросов.

GET-запрос: получение данных

GET — самый простой тип запроса. Он используется для получения данных от сервера. Пример:

import java.net.URI;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/users"))
    .GET() // явно указываем метод (можно опустить, GET по умолчанию)
    .build();

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

System.out.println("Статус: " + response.statusCode());
System.out.println("Тело ответа: " + response.body());

Метод send() выполняет синхронный запрос. Если нужно асинхронное выполнение, используйте sendAsync(), который возвращает CompletableFuture.

POST-запрос: отправка данных

POST используется для отправки данных на сервер. Чаще всего это JSON или форма. Рассмотрим оба варианта.

POST с JSON:

import java.net.http.HttpRequest.BodyPublishers;

String json = "{\"name\":\"Иван\",\"email\":\"ivan@example.com\"}";

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/users"))
    .header("Content-Type", "application/json")
    .POST(BodyPublishers.ofString(json))
    .build();

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

POST с формой (application/x-www-form-urlencoded):

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.stream.Collectors;

Map<String, String> formData = Map.of("username", "john", "password", "secret123");

String formBody = formData.entrySet().stream()
    .map(e -> URLEncoder.encode(e.getKey(), StandardCharsets.UTF_8) + "=" + 
               URLEncoder.encode(e.getValue(), StandardCharsets.UTF_8))
    .collect(Collectors.joining("&"));

HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/login"))
    .header("Content-Type", "application/x-www-form-urlencoded")
    .POST(BodyPublishers.ofString(formBody))
    .build();

PUT и DELETE запросы

Для обновления данных используется PUT, для удаления — DELETE. Синтаксис аналогичен POST:

// PUT запрос
HttpRequest putRequest = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/users/1"))
    .header("Content-Type", "application/json")
    .PUT(BodyPublishers.ofString("{\"name\":\"Обновленное имя\"}"))
    .build();

// DELETE запрос
HttpRequest deleteRequest = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/users/1"))
    .DELETE()
    .build();

3. Обработка ответа и работа с заголовками

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

Чтение заголовков ответа

Заголовки могут содержать важную информацию: тип контента, кэширование, токены и т.д.

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());

// Получаем все заголовки
HttpHeaders headers = response.headers();
System.out.println("Content-Type: " + headers.firstValue("Content-Type").orElse("нет"));
System.out.println("Все заголовки: " + headers.map());

Обработка статус-кодов и ошибок

HTTP-статусы делятся на категории: 2xx — успех, 4xx — ошибка клиента, 5xx — ошибка сервера. Важно проверять статус перед обработкой данных:

int                

Блоги

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