HTTP клиент на Java: делаем запросы правильно от А до Я
В современной разработке на Java взаимодействие с внешними веб-сервисами и REST API стало неотъемлемой частью практически любого приложения. Независимо от того, пишете ли вы микросервис, мобильное приложение или корпоративную систему, умение правильно отправлять HTTP-запросы — критически важный навык. В этой статье мы разберем все способы создания HTTP-клиента на Java: от классического HttpURLConnection до современных библиотек, таких как java.net.http.HttpClient, OkHttp и RestTemplate. Вы узнаете, как делать GET, POST, PUT и DELETE запросы, обрабатывать ответы и выбирать правильный инструмент для вашей задачи.
1. Классический подход: HttpURLConnection
На протяжении многих лет стандартным способом работы с HTTP в Java был класс HttpURLConnection. Он входит в состав JDK и не требует дополнительных зависимостей. Однако его API считается низкоуровневым и громоздким, особенно для сложных запросов.
Пример GET-запроса:
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) throws Exception {
URL url = new URL("https://api.example.com/users");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Accept", "application/json");
int responseCode = connection.getResponseCode();
System.out.println("Response Code: " + responseCode);
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());
}
}
Пример 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 jsonInputString = "{\"name\": \"John\", \"age\": 30}";
try (OutputStream os = connection.getOutputStream()) {
byte[] input = jsonInputString.getBytes("utf-8");
os.write(input, 0, input.length);
}
int responseCode = connection.getResponseCode();
System.out.println("Response Code: " + responseCode);
}
}
Плюсы: встроен в JDK, не требует библиотек.
Минусы: сложный код, нет поддержки HTTP/2, неудобная работа с таймаутами и ошибками.
2. Современный HttpClient (Java 11+)
Начиная с Java 11, в стандартную библиотеку был добавлен новый java.net.http.HttpClient. Он поддерживает HTTP/2, WebSocket, асинхронные запросы и предоставляет гораздо более чистый и современный API.
Синхронный GET-запрос:
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class ModernHttpClientExample {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/users"))
.header("Accept", "application/json")
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Status: " + response.statusCode());
System.out.println("Body: " + response.body());
}
}
Асинхронный POST-запрос:
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.concurrent.CompletableFuture;
public class AsyncPostExample {
public static void main(String[] args) {
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(10))
.build();
String json = "{\"name\": \"Jane\", \"age\": 25}";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.example.com/users"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();
CompletableFuture<HttpResponse<String>> future = client.sendAsync(request,
HttpResponse.BodyHandlers.ofString());
future.thenAccept(response -> {
System.out.println("Status: " + response.statusCode());
System.out.println("Body: " + response.body());
}).join();
}
}
Плюсы: современный API, HTTP/2, асинхронность, встроен в JDK.
Минусы: требует Java 11+, нет встроенной поддержки OAuth или сложных ретраев.
3. Популярные сторонние библиотеки: OkHttp и RestTemplate
Хотя встроенные средства покрывают большинство базовых сценариев, в реальных проектах часто используют сторонние библиотеки, которые предоставляют дополнительные возможности: автоматическое кеширование, повторные попытки, интерцепторы и интеграцию с JSON-парсерами.
OkHttp
OkHttp — одна из самых популярных библиотек для Android и Java. Она эффективна, поддерживает HTTP/2, WebSocket и очень проста в использовании.
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import java.io.IOException;
public class OkHttpExample {
public static void main(String[] args) throws IOException {
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(30, java.util.concurrent.TimeUnit.SECONDS)
.build();
// GET запрос
Request getRequest = new Request.Builder()
.url("https://api.example.com/users")
.addHeader("Accept", "application/json")
.build();
try (Response response = client.newCall(getRequest).execute()) {
System.out.println("GET Response: " + response.body().string());
}
// POST запрос
String json = "{\"name\": \"Alice\"}";
RequestBody body = RequestBody.create(json, MediaType.get("application/json"));
Request postRequest = new Request.Builder()
.url("https://api.example.com/users")
.post(body)
.build();
try (Response response = client.newCall(postRequest).execute()) {
System.out.println("POST Response: " + response.body().string());
}
}
}
RestTemplate (Spring)
Если вы используете Spring Framework, RestTemplate является стандартным решением. Однако в Spring 5+ его рекомендуют заменять на WebClient.
import org.springframework.web.client.RestTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
public class RestTemplateExample {
public static