5 способов выполнить HTTP-запросы в Java: от классики до новинок
Для кого эта статья:
- Java-разработчики, которые хотят улучшить свои навыки работы с HTTP-запросами
- Студенты и начинающие программисты, интересующиеся Java и веб-разработкой
Опытные разработчики, ищущие альтернативные подходы и библиотеки для работы с HTTP в Java
Взаимодействие с внешними API через HTTP-запросы — неотъемлемая часть современной Java-разработки. Будь то получение данных от платежного сервиса, интеграция с CRM или отправка push-уведомлений — работа с HTTP присутствует почти в каждом коммерческом проекте. Я протестировал пять наиболее востребованных способов реализации HTTP-запросов в Java, от классических подходов до новейших API, и готов поделиться рабочими примерами кода, которые можно скопировать в свой проект уже сегодня. 🚀
Если после прочтения статьи вы захотите углубить свои знания в сфере Java-разработки, обратите внимание на Курс Java-разработки от Skypro. На нём вы не только освоите работу с HTTP и REST API на практических примерах, но и научитесь создавать полноценные клиент-серверные приложения. Курс включает практику с реальными проектами и менторскую поддержку от действующих разработчиков.
Основные способы отправки HTTP-запросов в Java
Java предлагает разработчикам несколько вариантов для работы с HTTP-протоколом, от встроенных классов до специализированных библиотек. Выбор конкретного инструмента зависит от требований вашего проекта, версии Java и личных предпочтений.
Алексей Родионов, ведущий Java-разработчик
Когда я только начинал карьеру, один из первых моих проектов требовал интеграции с платежной системой. Я использовал HttpURLConnection, потому что "это же встроенный класс, значит, самый правильный". Спустя неделю отладки странного поведения и утечек соединений код превратился в лапшу из проверок и обработчиков исключений. После консультации с тимлидом мы перешли на Apache HttpClient, и объем кода сократился втрое. С тех пор я всегда оцениваю не только функциональность, но и удобство работы с API.
Рассмотрим пять основных подходов к отправке HTTP-запросов в Java:
| Метод | Тип | Минимальная версия Java | Особенности |
|---|---|---|---|
| HttpURLConnection | Встроенный класс | Java 1.1+ | Не требует дополнительных зависимостей, многословный API |
| Apache HttpClient | Внешняя библиотека | Java 6+ | Гибкая настройка, многофункциональность, популярность |
| Java 11 HttpClient | Встроенный класс | Java 11+ | Современный API, асинхронные запросы, поддержка HTTP/2 |
| Spring RestTemplate | Часть Spring Framework | Java 6+ (устаревает) | Интеграция со Spring, высокоуровневый API |
| OkHttp | Внешняя библиотека | Java 8+ | Высокая производительность, современный API, кэширование |
Каждый из этих подходов имеет свои сильные и слабые стороны. Далее рассмотрим их подробнее с примерами кода для типичных сценариев.

HttpURLConnection: встроенный метод для работы с HTTP
HttpURLConnection — это встроенный в Java класс для работы с HTTP, доступный начиная с самых ранних версий языка. Его главное преимущество — отсутствие необходимости подключать дополнительные библиотеки.
Базовый пример GET-запроса с HttpURLConnection:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class HttpURLConnectionExample {
public static void main(String[] args) {
try {
// Создаем объект URL
URL url = new URL("https://api.example.com/data");
// Открываем соединение
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// Устанавливаем метод запроса
connection.setRequestMethod("GET");
// Добавляем заголовки
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("User-Agent", "Java HttpURLConnection Example");
// Получаем код ответа
int responseCode = connection.getResponseCode();
System.out.println("Response Code: " + responseCode);
// Читаем ответ
BufferedReader reader;
if (responseCode >= 200 && responseCode < 300) {
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
} else {
reader = new BufferedReader(new InputStreamReader(connection.getErrorStream()));
}
String line;
StringBuilder response = new StringBuilder();
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
// Выводим результат
System.out.println(response.toString());
// Закрываем соединение
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Для отправки POST-запроса с данными нужно сделать несколько дополнительных шагов:
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
// ... предыдущий импорт ...
public class HttpURLConnectionPostExample {
public static void main(String[] args) {
try {
URL url = new URL("https://api.example.com/submit");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// Настраиваем соединение для POST
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.setDoOutput(true);
// Данные для отправки
String jsonInputString = "{\"name\": \"John\", \"job\": \"Developer\"}";
// Отправляем данные
try(OutputStream os = connection.getOutputStream()) {
byte[] input = jsonInputString.getBytes("utf-8");
os.write(input, 0, input.length);
}
// Чтение ответа, как в предыдущем примере
// ...
} catch (Exception e) {
e.printStackTrace();
}
}
}
Преимущества HttpURLConnection:
- Не требует внешних зависимостей
- Доступен во всех версиях Java
- Минимальный объем добавляемого кода в проект
Недостатки HttpURLConnection:
- Многословный и неудобный API
- Необходимость ручного управления ресурсами
- Отсутствие встроенной поддержки многих современных функций (кэширование, пулы соединений)
- Сложность работы с запросами, требующими сложных заголовков или аутентификации
Apache HttpClient: мощная библиотека с гибкой настройкой
Apache HttpClient — одна из самых популярных библиотек для работы с HTTP в Java, предоставляющая богатый функционал и гибкость настройки. Для использования необходимо добавить зависимость в pom.xml (Maven) или build.gradle (Gradle). 🛠️
Maven-зависимость:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
Gradle-зависимость:
implementation 'org.apache.httpcomponents:httpclient:4.5.13'
Пример выполнения GET-запроса с Apache HttpClient:
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
public class ApacheHttpClientExample {
public static void main(String[] args) {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
// Создаем объект запроса
HttpGet request = new HttpGet("https://api.example.com/data");
// Добавляем заголовки
request.addHeader("Content-Type", "application/json");
// Выполняем запрос
try (CloseableHttpResponse response = httpClient.execute(request)) {
// Получаем статус-код
int statusCode = response.getStatusLine().getStatusCode();
System.out.println("Status Code: " + statusCode);
// Получаем тело ответа
HttpEntity entity = response.getEntity();
if (entity != null) {
String result = EntityUtils.toString(entity);
System.out.println("Response: " + result);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Пример POST-запроса с отправкой JSON-данных:
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
public class ApacheHttpClientPostExample {
public static void main(String[] args) {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
HttpPost request = new HttpPost("https://api.example.com/submit");
// Устанавливаем заголовки
request.addHeader("Content-Type", "application/json");
// Создаем JSON-тело
String jsonBody = "{\"name\":\"John\",\"job\":\"Developer\"}";
StringEntity entity = new StringEntity(jsonBody);
request.setEntity(entity);
// Выполняем запрос
try (CloseableHttpResponse response = httpClient.execute(request)) {
// Обработка ответа, как в предыдущем примере
// ...
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Apache HttpClient предлагает множество возможностей для настройки, включая:
- Пул соединений для повышения производительности
- Настройка тайм-аутов и стратегий повторных попыток
- Поддержка различных схем аутентификации (Basic, OAuth, JWT)
- Прокси-серверы и SSL/TLS настройки
- Обработка cookies и сессий
Пример настройки пула соединений и тайм-аутов:
import org.apache.http.client.config.RequestConfig;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
public class AdvancedHttpClientConfig {
public static CloseableHttpClient createCustomHttpClient() {
// Создаем пул соединений
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
connectionManager.setMaxTotal(100); // Максимум 100 соединений всего
connectionManager.setDefaultMaxPerRoute(20); // Максимум 20 соединений на один хост
// Настраиваем тайм-ауты (в миллисекундах)
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(5000) // ожидание подключения
.setConnectionRequestTimeout(5000) // ожидание получения соединения из пула
.setSocketTimeout(30000) // ожидание данных
.build();
// Создаем и возвращаем клиент
return HttpClientBuilder.create()
.setConnectionManager(connectionManager)
.setDefaultRequestConfig(requestConfig)
.build();
}
}
Максим Сорокин, Java-архитектор
В проекте для крупного банка мы столкнулись с проблемой при интеграции с платежным шлюзом: API требовало сложной аутентификации и строгого таймменеджмента соединений. После нескольких падений при пиковых нагрузках мы перешли на кастомную конфигурацию Apache HttpClient с пулом соединений и стратегией повторных попыток. Нагрузочное тестирование показало рост производительности на 63% и устранение ошибок тайм-аута. Ключевым оказалась не только настройка пула (мы установили defaultMaxPerRoute=50 и MaxTotal=200), но и конфигурация стратегии повторов с экспоненциальной задержкой для разных типов ошибок.
Java 11 HttpClient: современный API для HTTP-запросов
Начиная с Java 11, в стандартную библиотеку был добавлен новый класс HttpClient, который предлагает современный и удобный API для работы с HTTP. Он поддерживает HTTP/2, асинхронные запросы и имеет более чистый интерфейс, чем HttpURLConnection. 🔄
Базовый пример GET-запроса с Java 11 HttpClient:
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class Java11HttpClientExample {
public static void main(String[] args) {
try {
// Создаем клиент
HttpClient client = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2) // Используем HTTP/2
.connectTimeout(Duration.ofSeconds(5))
.build();
// Создаем запрос
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/data"))
.header("Content-Type", "application/json")
.GET()
.build();
// Отправляем запрос и получаем ответ как строку
HttpResponse<String> response = client.send(
request,
HttpResponse.BodyHandlers.ofString()
);
// Выводим результаты
System.out.println("Status Code: " + response.statusCode());
System.out.println("Response: " + response.body());
} catch (Exception e) {
e.printStackTrace();
}
}
}
Пример POST-запроса с отправкой JSON-данных:
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Java11HttpClientPostExample {
public static void main(String[] args) {
try {
HttpClient client = HttpClient.newHttpClient();
// Данные для отправки
String jsonBody = "{\"name\":\"John\",\"job\":\"Developer\"}";
// Создаем POST-запрос с телом
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/submit"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(jsonBody))
.build();
// Отправляем запрос
HttpResponse<String> response = client.send(
request,
HttpResponse.BodyHandlers.ofString()
);
// Выводим результаты
System.out.println("Status Code: " + response.statusCode());
System.out.println("Response: " + response.body());
} catch (Exception e) {
e.printStackTrace();
}
}
}
Одно из главных преимуществ Java 11 HttpClient — поддержка асинхронных запросов с использованием CompletableFuture:
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.concurrent.CompletableFuture;
public class Java11AsyncHttpClientExample {
public static void main(String[] args) {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/data"))
.build();
// Асинхронная отправка запроса
CompletableFuture<HttpResponse<String>> futureResponse = client.sendAsync(
request,
HttpResponse.BodyHandlers.ofString()
);
// Обработка результата, когда он будет доступен
futureResponse
.thenApply(HttpResponse::body)
.thenAccept(System.out::println)
.join(); // Ждем завершения (для примера)
System.out.println("Запрос отправлен асинхронно");
}
}
Java 11 HttpClient также поддерживает параллельную обработку множества запросов:
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
public class MultipleAsyncRequestsExample {
public static void main(String[] args) {
HttpClient client = HttpClient.newHttpClient();
// Список URL для запросов
List<URI> targets = List.of(
URI.create("https://api.example.com/users"),
URI.create("https://api.example.com/products"),
URI.create("https://api.example.com/orders")
);
// Создаем и отправляем запросы асинхронно
List<CompletableFuture<String>> futures = targets.stream()
.map(uri -> HttpRequest.newBuilder(uri).build())
.map(request -> client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body))
.collect(Collectors.toList());
// Ожидаем завершения всех запросов
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
// Выводим результаты
futures.forEach(future -> {
try {
System.out.println(future.get());
} catch (Exception e) {
e.printStackTrace();
}
});
}
}
| Функция | HttpURLConnection | Java 11 HttpClient |
|---|---|---|
| Асинхронные запросы | Нет | Да (CompletableFuture) |
| HTTP/2 поддержка | Нет | Да |
| WebSocket | Нет | Да |
| Потоковая передача запросов/ответов | Ограниченная | Расширенная |
| Чистота API | Низкая (многословный) | Высокая (цепочка методов) |
| Удобство обработки ответов | Низкое (ручное) | Высокое (BodyHandlers) |
Преимущества Java 11 HttpClient:
- Современный и понятный API
- Встроенная поддержка HTTP/2
- Асинхронные запросы через CompletableFuture
- Поддержка WebSocket
- Различные обработчики ответов (строки, байты, потоки, JSON)
Недостатки Java 11 HttpClient:
- Требуется Java 11 или выше
- Меньше возможностей для тонкой настройки по сравнению с Apache HttpClient
- Отсутствие встроенной поддержки некоторых продвинутых функций (сложная аутентификация, кеширование)
Spring RestTemplate и OkHttp: альтернативы для разработчиков
Помимо уже рассмотренных вариантов, в экосистеме Java существуют и другие популярные решения для работы с HTTP: Spring RestTemplate (и его преемник WebClient) и библиотека OkHttp от Square.
Spring RestTemplate популярен среди разработчиков, использующих экосистему Spring:
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
public class SpringRestTemplateExample {
public static void main(String[] args) {
// Создаем экземпляр RestTemplate
RestTemplate restTemplate = new RestTemplate();
// GET-запрос и преобразование ответа в String
String getResult = restTemplate.getForObject(
"https://api.example.com/data",
String.class
);
System.out.println("GET Response: " + getResult);
// Подготовка заголовков для POST-запроса
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
// Создаем тело запроса
String jsonBody = "{\"name\":\"John\",\"job\":\"Developer\"}";
HttpEntity<String> entity = new HttpEntity<>(jsonBody, headers);
// Отправляем POST-запрос
ResponseEntity<String> postResponse = restTemplate.postForEntity(
"https://api.example.com/submit",
entity,
String.class
);
System.out.println("POST Status Code: " + postResponse.getStatusCodeValue());
System.out.println("POST Response: " + postResponse.getBody());
}
}
Начиная с Spring 5, рекомендуется использовать реактивный WebClient вместо RestTemplate:
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
public class SpringWebClientExample {
public static void main(String[] args) {
// Создаем базовый WebClient
WebClient client = WebClient.create("https://api.example.com");
// GET-запрос
String response = client.get()
.uri("/data")
.retrieve()
.bodyToMono(String.class)
.block(); // Блокирующий вызов для примера
System.out.println("Response: " + response);
// POST-запрос с JSON телом
String jsonBody = "{\"name\":\"John\",\"job\":\"Developer\"}";
Mono<String> postResponse = client.post()
.uri("/submit")
.contentType(org.springframework.http.MediaType.APPLICATION_JSON)
.bodyValue(jsonBody)
.retrieve()
.bodyToMono(String.class);
System.out.println("POST Response: " + postResponse.block());
}
}
OkHttp — популярная библиотека от Square, известная своей высокой производительностью:
import okhttp3.*;
import java.io.IOException;
public class OkHttpExample {
// OkHttpClient рекомендуется создавать один раз и переиспользовать
private final OkHttpClient client = new OkHttpClient();
public static void main(String[] args) throws IOException {
OkHttpExample example = new OkHttpExample();
example.sendGetRequest();
example.sendPostRequest();
}
private void sendGetRequest() throws IOException {
Request request = new Request.Builder()
.url("https://api.example.com/data")
.header("Content-Type", "application/json")
.build();
try (Response response = client.newCall(request).execute()) {
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
}
System.out.println(response.body().string());
}
}
private void sendPostRequest() throws IOException {
String jsonBody = "{\"name\":\"John\",\"job\":\"Developer\"}";
RequestBody body = RequestBody.create(
jsonBody,
MediaType.parse("application/json")
);
Request request = new Request.Builder()
.url("https://api.example.com/submit")
.post(body)
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println(response.body().string());
}
}
}
OkHttp также поддерживает асинхронные запросы с использованием колбеков:
import okhttp3.*;
import java.io.IOException;
public class OkHttpAsyncExample {
private final OkHttpClient client = new OkHttpClient();
public static void main(String[] args) {
OkHttpAsyncExample example = new OkHttpAsyncExample();
example.sendAsyncGetRequest();
// Ждем небольшое время для выполнения асинхронного запроса
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void sendAsyncGetRequest() {
Request request = new Request.Builder()
.url("https://api.example.com/data")
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException {
try (ResponseBody responseBody = response.body()) {
if (!response.isSuccessful()) {
System.out.println("Unexpected code " + response);
} else {
System.out.println(responseBody.string());
}
}
}
});
System.out.println("Асинхронный запрос отправлен");
}
}
Сравнение всех рассмотренных методов:
- HttpURLConnection: встроенный, но устаревший подход, требующий много кода
- Apache HttpClient: мощный и гибко настраиваемый, но может быть избыточным для простых задач
- Java 11 HttpClient: современный встроенный API с асинхронной поддержкой
- Spring RestTemplate/WebClient: удобен при использовании Spring
- OkHttp: быстрый и компактный, хорошо подходит для мобильных и ресурсоограниченных приложений
Рекомендации по выбору:
- Для простых приложений на Java 11+: используйте встроенный HttpClient
- Для Spring-приложений: WebClient (современные реактивные) или RestTemplate (устаревшие)
- Для сложных сценариев с тонкой настройкой: Apache HttpClient
- Для Android или ресурсоограниченных сред: OkHttp
- Если необходима переносимость без внешних зависимостей: HttpURLConnection
Эффективная работа с HTTP-запросами — фундаментальный навык для Java-разработчика в эпоху распределенных систем и микросервисной архитектуры. Выбор инструмента определяется не только технической задачей, но и контекстом проекта — используемым фреймворком, требованиями к производительности и удобству поддержки. Начинающим разработчикам стоит сначала освоить Java 11 HttpClient как наиболее современный и интуитивно понятный API, а затем уже переходить к специализированным решениям для конкретных задач.