HTTP клиент на Java: делаем запросы правильно
В современной разработке практически любое приложение взаимодействует с внешними сервисами через HTTP. Будь то REST API, загрузка данных с сервера или отправка форм — умение работать с HTTP-запросами является обязательным навыком для Java-разработчика. В этой статье мы разберём, как создать HTTP клиент на Java, используя как стандартные средства, так и популярные сторонние библиотеки. Вы узнаете, как правильно выполнять GET и POST запросы, обрабатывать ошибки и парсить ответы.
1. Классический подход: HttpURLConnection
Долгое время стандартным способом работы с HTTP в Java был класс HttpURLConnection. Он входит в пакет java.net и не требует установки дополнительных зависимостей. Рассмотрим пример выполнения GET-запроса:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class SimpleHttpClient {
public static void main(String[] args) throws Exception {
URL url = new URL("https://api.example.com/data");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept", "application/json");
int responseCode = connection.getResponseCode();
System.out.println("Response Code: " + responseCode);
if (responseCode == HttpURLConnection.HTTP_OK) {
BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String inputLine;
StringBuilder response = new StringBuilder();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println("Response: " + response.toString());
} else {
System.out.println("GET request failed");
}
connection.disconnect();
}
}
Для POST-запроса с передачей JSON-данных код будет немного сложнее:
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
public class PostExample {
public static void main(String[] args) throws Exception {
URL url = new URL("https://api.example.com/users");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
connection.setDoOutput(true);
String jsonInput = "{\"name\":\"John\",\"email\":\"john@example.com\"}";
try (OutputStream os = connection.getOutputStream()) {
byte[] input = jsonInput.getBytes("utf-8");
os.write(input, 0, input.length);
}
int responseCode = connection.getResponseCode();
System.out.println("POST Response Code: " + responseCode);
if (responseCode == HttpURLConnection.HTTP_CREATED) {
// Чтение ответа аналогично GET
}
connection.disconnect();
}
}
Плюсы HttpURLConnection:
- Не требует дополнительных библиотек
- Полный контроль над запросом
- Поддержка всех HTTP-методов
Минусы:
- Многословный и неудобный API
- Сложно обрабатывать ошибки
- Нет встроенной поддержки современных протоколов (HTTP/2)
2. Современный стандарт: HttpClient (Java 11+)
Начиная с Java 11, в стандартную библиотеку был добавлен новый java.net.http.HttpClient. Он предоставляет современный, асинхронный и гораздо более удобный API. Вот как выглядит GET-запрос с его помощью:
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class ModernHttpClient {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/data"))
.header("Accept", "application/json")
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Status code: " + response.statusCode());
System.out.println("Response body: " + response.body());
}
}
Для POST-запроса с телом:
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class ModernPostExample {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
String jsonBody = "{\"name\":\"Jane\",\"email\":\"jane@example.com\"}";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/users"))
.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());
}
}
HttpClient поддерживает как синхронные (send()), так и асинхронные (sendAsync()) вызовы. Асинхронный вариант возвращает CompletableFuture, что упрощает работу с реактивными потоками.
Преимущества HttpClient:
- Чистый и лаконичный API
- Встроенная поддержка HTTP/2 и WebSocket
- Асинхронные запросы без сторонних библиотек
- Автоматическое управление соединениями
3. Популярные сторонние библиотеки: OkHttp и Apache HttpClient
Несмотря на появление встроенного HttpClient, многие разработчики предпочитают использовать проверенные сторонние библиотеки. Рассмотрим две самые популярные: OkHttp и Apache HttpClient.
OkHttp
OkHttp — это современная, быстрая и удобная библиотека от Square. Она поддерживает HTTP/2, автоматическую повторную попытку при ошибках и перехватчики (interceptors). Для её использования добавьте зависимость в Maven:
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>4.12.0</version>
</dependency>
Пример GET-запроса с OkHttp:
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class OkHttpExample {
public static void main(String[] args) throws Exception {
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://api.example.com/data")
.addHeader("Accept", "application/json")
.build();
try (Response response = client.newCall(request).execute()) {
System.out.println("Status: " + response.code());
System.out.println("Body: " + response.body().string());
}
}
}
POST-запрос с JSON:
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import