Как использовать URLConnection в Java: основы работы с HTTP-запросами
Для кого эта статья:
- Java-разработчики, работающие с интеграцией API
- Студенты и начинающие разработчики, стремящиеся освоить сетевое взаимодействие в Java
Профессионалы, желающие углубить свои знания о низкоуровневом сетевом программировании
Java-разработчики периодически сталкиваются с необходимостью интеграции своих приложений с внешними API. Вариантов реализации сетевых взаимодействий существует множество: от современных фреймворков вроде OkHttp и Apache HttpClient до встроенных решений. Среди последних класс URLConnection остаётся фундаментальным инструментом для HTTP-коммуникаций, который поставляется с JDK с самых ранних версий. Несмотря на появление более удобных альтернатив, знание этого API по-прежнему является обязательным для профессионального Java-разработчика. Разберём, как использовать URLConnection для отправки разных типов запросов и обработки ответов. 🔍
Мечтаете писать безопасный и эффективный сетевой код на Java? На курсе Java-разработки от Skypro вы освоите не только основы URLConnection, но и продвинутые техники асинхронной работы с HTTP, Spring WebClient и реактивное программирование. Наши выпускники с лёгкостью интегрируют сторонние API и создают высоконагруженные сервисы с миллионами запросов. Станьте востребованным Java-разработчиком всего за 9 месяцев!
Основы URLConnection: принципы работы с HTTP в Java
URLConnection представляет собой абстрактный класс в пакете java.net, который обеспечивает базовый механизм для взаимодействия с ресурсами, идентифицируемыми URL. Для работы с HTTP-запросами обычно используется его подкласс HttpURLConnection. Эти классы существуют с первых версий Java и до сих пор остаются частью стандартной библиотеки.
Базовый принцип работы с URLConnection состоит из нескольких шагов:
- Создание объекта URL, представляющего адрес запроса
- Получение экземпляра URLConnection через метод URL.openConnection()
- Настройка соединения (метод запроса, заголовки и т.д.)
- Установление соединения с помощью connect()
- Отправка данных (для запросов, требующих тело)
- Чтение ответа от сервера
- Закрытие соединения
URLConnection может показаться многословным и требует ручного управления ресурсами, но предоставляет полный контроль над всеми аспектами HTTP-взаимодействия. 💪
Рассмотрим простейший пример получения содержимого веб-страницы:
URL url = new URL("https://example.com");
URLConnection connection = url.openConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
reader.close();
Для HTTP-запросов рекомендуется использовать HttpURLConnection, который добавляет специфические для HTTP методы:
URL url = new URL("https://api.example.com/data");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// Настройка метода запроса
connection.setRequestMethod("GET");
// Получение кода ответа
int responseCode = connection.getResponseCode();
System.out.println("Response Code: " + responseCode);
// Закрытие соединения
connection.disconnect();
Важно отметить основные характеристики URLConnection, которые влияют на его использование:
| Характеристика | Описание | Влияние на разработку |
|---|---|---|
| Блокирующие операции | Все операции ввода-вывода блокируют выполнение потока | Необходимо обрабатывать запросы в отдельных потоках |
| Ручное управление ресурсами | Требует явного закрытия потоков | Повышенный риск утечек ресурсов |
| Отсутствие пула соединений | Каждый запрос создает новое соединение | Снижение производительности при множественных запросах |
| Нет встроенной поддержки JSON | Требуется ручная сериализация/десериализация | Необходимо использовать дополнительные библиотеки |
Александр Петров, Senior Java Developer
Когда я начал работать с микросервисной архитектурой в 2018 году, моей первой задачей было интегрировать платежный шлюз. Я использовал HttpURLConnection, потому что это была "классика" Java. Система работала нормально при небольшой нагрузке, но когда трафик вырос до 100 запросов в секунду, начались проблемы.
Соединения не закрывались должным образом, вызывая утечки ресурсов. После 12 часов отладки я обнаружил, что забыл вызвать connection.disconnect() в одном из блоков catch. Теперь я использую try-with-resources и никогда не забываю о закрытии ресурсов:
JavaСкопировать кодtry (InputStream in = connection.getInputStream()) { // чтение данных } finally { connection.disconnect(); }Этот опыт показал мне, насколько важно понимать низкоуровневые механизмы сетевого взаимодействия в Java, даже при использовании современных библиотек.

GET-запросы с URLConnection: пошаговая реализация
GET-запросы являются наиболее распространенным типом HTTP-запросов и используются для получения данных с сервера. С помощью URLConnection их реализация достаточно прямолинейна. Рассмотрим процесс шаг за шагом. 🚶♂️
Базовый пример GET-запроса выглядит следующим образом:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class SimpleGetRequest {
public static void main(String[] args) {
try {
// 1. Создаем URL
URL url = new URL("https://api.example.com/users");
// 2. Открываем соединение
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 3. Настраиваем метод запроса
connection.setRequestMethod("GET");
// 4. Устанавливаем таймаут соединения (5 секунд)
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
// 5. Получаем код ответа
int statusCode = connection.getResponseCode();
System.out.println("Status Code: " + statusCode);
// 6. Читаем ответ
BufferedReader reader;
if (statusCode >= 200 && statusCode < 300) {
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
} else {
reader = new BufferedReader(new InputStreamReader(connection.getErrorStream()));
}
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
reader.close();
// 7. Выводим результат
System.out.println("Response: " + response.toString());
// 8. Закрываем соединение
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
}
При отправке GET-запросов часто требуется передать параметры запроса. Это можно сделать, добавив их к URL в формате query string. Вместо ручного конструирования строки запроса лучше использовать класс URLEncoder для корректного кодирования параметров:
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
// ...
String baseUrl = "https://api.example.com/search";
String query = "Java Programming";
String encodedQuery = URLEncoder.encode(query, StandardCharsets.UTF_8.toString());
URL url = new URL(baseUrl + "?q=" + encodedQuery + "&limit=10");
Для более сложных запросов с множеством параметров удобно использовать StringBuilder:
StringBuilder queryBuilder = new StringBuilder();
queryBuilder.append("?");
queryBuilder.append("q=").append(URLEncoder.encode("Java Programming", StandardCharsets.UTF_8.toString()));
queryBuilder.append("&limit=").append(10);
queryBuilder.append("&sort=").append(URLEncoder.encode("relevance", StandardCharsets.UTF_8.toString()));
URL url = new URL(baseUrl + queryBuilder.toString());
При реализации GET-запросов с URLConnection следует учитывать несколько важных моментов:
- Обработка ошибок: Всегда проверяйте код ответа перед чтением данных
- Кодирование URL: Используйте URLEncoder для параметров запроса
- Таймауты: Устанавливайте разумные значения таймаутов
- Освобождение ресурсов: Закрывайте потоки и соединения
- Повторные попытки: Реализуйте механизм повторных попыток для ненадежных соединений
Рассмотрим пример более продвинутого GET-запроса с обработкой ошибок и повторными попытками:
public String sendGetRequestWithRetry(String urlString, int maxRetries) {
int retryCount = 0;
while (retryCount < maxRetries) {
HttpURLConnection connection = null;
try {
URL url = new URL(urlString);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);
connection.setReadTimeout(15000);
int statusCode = connection.getResponseCode();
if (statusCode >= 200 && statusCode < 300) {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(connection.getInputStream()))) {
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
return response.toString();
}
} else if (statusCode >= 500) {
// Сервер временно недоступен, повторяем
retryCount++;
Thread.sleep(1000 * retryCount); // Экспоненциальная задержка
continue;
} else {
// Клиентская ошибка, не повторяем
throw new IOException("HTTP Error: " + statusCode +
" " + connection.getResponseMessage());
}
} catch (IOException e) {
retryCount++;
if (retryCount >= maxRetries) {
throw new RuntimeException("Failed after " + maxRetries + " retries", e);
}
try {
Thread.sleep(1000 * retryCount);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
throw new RuntimeException("Interrupted during retry delay", ie);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("Interrupted during retry delay", e);
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
throw new RuntimeException("Should not reach here");
}
Отправка POST-запросов и передача данных на сервер
POST-запросы используются для отправки данных на сервер для создания или обновления ресурсов. В отличие от GET-запросов, они могут содержать тело запроса с произвольными данными. Рассмотрим, как реализовать POST-запросы с помощью URLConnection. 📤
Основные шаги при отправке POST-запроса:
- Создание URL и открытие соединения
- Установка метода запроса в "POST"
- Настройка соединения для отправки данных (setDoOutput)
- Установка заголовков Content-Type и Content-Length
- Отправка данных через OutputStream
- Получение и обработка ответа
Простой пример отправки формы через POST-запрос:
import java.io.DataOutputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
public class SimplePostRequest {
public static void main(String[] args) {
try {
// 1. Создаем URL
URL url = new URL("https://api.example.com/submit");
// 2. Открываем соединение
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// 3. Настраиваем метод запроса
connection.setRequestMethod("POST");
// 4. Указываем, что будем отправлять данные
connection.setDoOutput(true);
// 5. Формируем данные для отправки
String name = "John Doe";
String email = "john.doe@example.com";
String postData = "name=" + URLEncoder.encode(name, StandardCharsets.UTF_8.toString()) +
"&email=" + URLEncoder.encode(email, StandardCharsets.UTF_8.toString());
// 6. Устанавливаем заголовки
byte[] postDataBytes = postData.getBytes(StandardCharsets.UTF_8);
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
connection.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length));
// 7. Отправляем данные
try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) {
outputStream.write(postDataBytes);
}
// 8. Получаем ответ
int responseCode = connection.getResponseCode();
System.out.println("Response Code: " + responseCode);
// 9. Читаем ответ
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(connection.getInputStream()))) {
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
System.out.println("Response: " + response.toString());
}
// 10. Закрываем соединение
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
}
Для отправки JSON-данных, что часто требуется при работе с современными API, необходимо изменить Content-Type и формат данных:
// JSON данные
String jsonInputString = "{\"name\": \"John Doe\", \"email\": \"john.doe@example.com\"}";
// Устанавливаем заголовки
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("Accept", "application/json");
// Отправляем данные
try (OutputStream os = connection.getOutputStream()) {
byte[] input = jsonInputString.getBytes(StandardCharsets.UTF_8);
os.write(input, 0, input.length);
}
Также возможна отправка данных в формате multipart/form-data, который используется для загрузки файлов:
// Определяем границу частей
String boundary = "===" + System.currentTimeMillis() + "===";
// Устанавливаем заголовок Content-Type с boundary
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
// Получаем выходной поток
try (OutputStream os = connection.getOutputStream();
PrintWriter writer = new PrintWriter(new OutputStreamWriter(os, StandardCharsets.UTF_8), true)) {
// Добавляем текстовое поле
writer.append("--" + boundary).append("\r\n");
writer.append("Content-Disposition: form-data; name=\"username\"").append("\r\n");
writer.append("Content-Type: text/plain; charset=UTF-8").append("\r\n");
writer.append("\r\n");
writer.append("JohnDoe").append("\r\n");
// Добавляем файловое поле
writer.append("--" + boundary).append("\r\n");
writer.append("Content-Disposition: form-data; name=\"file\"; filename=\"example.txt\"").append("\r\n");
writer.append("Content-Type: text/plain").append("\r\n");
writer.append("\r\n");
writer.flush();
// Записываем содержимое файла
Files.copy(Paths.get("example.txt"), os);
os.flush();
writer.append("\r\n");
// Завершаем multipart/form-data
writer.append("--" + boundary + "--").append("\r\n");
}
Сравнение различных форматов данных для POST-запросов:
| Формат | Content-Type | Использование | Преимущества | Недостатки |
|---|---|---|---|---|
| application/x-www-form-urlencoded | application/x-www-form-urlencoded | Отправка данных формы | Простота реализации, хорошая поддержка | Неэффективен для больших объёмов данных |
| application/json | application/json | Работа с RESTful API | Поддержка сложных структур данных | Требует парсинга JSON |
| multipart/form-data | multipart/form-data | Загрузка файлов | Поддержка бинарных данных | Сложнее в реализации |
| text/plain | text/plain | Отправка простого текста | Максимальная простота | Ограниченная функциональность |
Мария Соколова, Lead Java Developer
В одном из проектов мы столкнулись с необходимостью создания микросервиса, который должен был отправлять данные в систему аналитики через устаревший API. Эта система принимала только формат multipart/form-data с десятками полей и несколькими файлами в каждом запросе.
Мы начали с реализации на URLConnection, но код быстро превратился в монстра – более 200 строк на один запрос. Каждое изменение в структуре данных требовало кропотливого обновления кода формирования multipart-границ и заголовков.
После трех недель борьбы мы создали собственную обертку вокруг URLConnection:
JavaСкопировать кодMultipartBuilder builder = new MultipartBuilder() .addTextField("username", "john") .addTextField("company", "acme") .addFileField("report", new File("report.xlsx")) .addFileField("logs", new File("logs.zip")); String response = builder.send("https://analytics-api.example.org/upload");Эта абстракция скрывала всю сложность работы с multipart/form-data и существенно упростила сопровождение кода. Главный урок: даже с базовыми API можно построить элегантные решения, если правильно абстрагировать сложности.
Настройка заголовков и работа с cookies в URLConnection
Заголовки HTTP играют ключевую роль в протоколе HTTP, определяя метаданные запроса или ответа. С помощью URLConnection вы можете как устанавливать заголовки для исходящих запросов, так и читать заголовки из ответов. Cookies, в свою очередь, представляют собой особый тип заголовков, используемый для сохранения состояния между запросами. 🍪
Рассмотрим, как устанавливать различные заголовки для HTTP-запроса:
URL url = new URL("https://api.example.com/data");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// Установка пользовательского User-Agent
connection.setRequestProperty("User-Agent", "Mozilla/5.0 MyApp/1.0");
// Установка заголовка Accept для указания предпочтительного формата ответа
connection.setRequestProperty("Accept", "application/json");
// Установка заголовка Authorization для базовой аутентификации
String auth = "username:password";
byte[] encodedAuth = Base64.getEncoder().encode(auth.getBytes(StandardCharsets.UTF_8));
String authHeader = "Basic " + new String(encodedAuth);
connection.setRequestProperty("Authorization", authHeader);
// Установка заголовка для кеширования
connection.setRequestProperty("Cache-Control", "no-cache");
Часто используемые HTTP-заголовки:
- User-Agent – идентификация клиента
- Accept – предпочтительные типы содержимого ответа
- Content-Type – тип содержимого запроса
- Authorization – данные для аутентификации
- Cache-Control – директивы кеширования
- Connection – опции управления соединением
- Cookie – данные cookie
- Accept-Encoding – поддерживаемые алгоритмы сжатия
Для чтения заголовков из ответа можно использовать следующие методы:
// Получение одного заголовка по имени
String contentType = connection.getHeaderField("Content-Type");
System.out.println("Content-Type: " + contentType);
// Получение всех заголовков
Map<String, List<String>> headers = connection.getHeaderFields();
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
String key = entry.getKey();
List<String> values = entry.getValue();
if (key == null) {
System.out.println("Status line: " + values.get(0));
} else {
for (String value : values) {
System.out.println(key + ": " + value);
}
}
}
Работа с cookies требует особого внимания. В Java существует специальный класс CookieManager для управления cookies:
// Включение поддержки cookies
CookieManager cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager);
// Настройка политики принятия cookies
cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
// Первый запрос (сервер установит cookies)
URL url1 = new URL("https://example.com/login");
HttpURLConnection conn1 = (HttpURLConnection) url1.openConnection();
// ... настройка и выполнение запроса
// Последующий запрос (cookies будут отправлены автоматически)
URL url2 = new URL("https://example.com/profile");
HttpURLConnection conn2 = (HttpURLConnection) url2.openConnection();
// ... настройка и выполнение запроса
// Получение текущих cookies
CookieStore cookieStore = cookieManager.getCookieStore();
List<HttpCookie> cookies = cookieStore.getCookies();
for (HttpCookie cookie : cookies) {
System.out.println("Cookie: " + cookie.getName() + "=" + cookie.getValue());
}
Для более тонкого контроля над cookies можно реализовать ручное управление:
// Получение cookies из ответа
String cookiesHeader = connection.getHeaderField("Set-Cookie");
if (cookiesHeader != null) {
// Сохранение cookies для последующих запросов
Map<String, String> cookiesMap = new HashMap<>();
for (String cookie : cookiesHeader.split(";")) {
String[] parts = cookie.split("=", 2);
if (parts.length == 2) {
cookiesMap.put(parts[0].trim(), parts[1].trim());
}
}
// В следующем запросе
StringBuilder cookieString = new StringBuilder();
for (Map.Entry<String, String> entry : cookiesMap.entrySet()) {
if (cookieString.length() > 0) {
cookieString.append("; ");
}
cookieString.append(entry.getKey()).append("=").append(entry.getValue());
}
nextConnection.setRequestProperty("Cookie", cookieString.toString());
}
При работе с заголовками и cookies следует учитывать несколько важных моментов:
- Заголовки необходимо устанавливать до вызова connect() или getInputStream()
- Имена заголовков не чувствительны к регистру, но значения могут быть
- Некоторые заголовки могут иметь несколько значений
- CookieManager автоматически обрабатывает домены и пути для cookies
- При ручном управлении cookies необходимо учитывать атрибуты Domain, Path, Expires, Max-Age, Secure и HttpOnly
Обработка HTTP-ответов и потоковое чтение данных
После отправки HTTP-запроса необходимо правильно обработать полученный ответ. URLConnection предоставляет несколько способов для чтения данных из ответа сервера, включая потоковое чтение для эффективной обработки больших объемов данных. 📊
Прежде всего, при обработке ответа необходимо проверить статус-код HTTP:
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
// ... настройка и выполнение запроса
int statusCode = connection.getResponseCode();
String statusMessage = connection.getResponseMessage();
System.out.println("Status: " + statusCode + " " + statusMessage);
if (statusCode >= 200 && statusCode < 300) {
// Успешный ответ
// Читаем данные из getInputStream()
} else {
// Ошибка
// Читаем сообщение об ошибке из getErrorStream()
}
Основные статус-коды HTTP и их обработка:
- 2xx (Success) – запрос успешно обработан
- 3xx (Redirection) – необходимо выполнить перенаправление
- 4xx (Client Error) – ошибка в запросе клиента
- 5xx (Server Error) – ошибка на сервере
Для чтения данных из ответа можно использовать несколько подходов. Самый простой – чтение всего ответа в строку:
private String readResponse(HttpURLConnection connection) throws IOException {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(connection.getInputStream()))) {
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
return response.toString();
}
}
Для обработки бинарных данных, например, при скачивании файлов, следует использовать InputStream напрямую:
private void downloadFile(HttpURLConnection connection, String filePath) throws IOException {
try (InputStream inputStream = connection.getInputStream();
FileOutputStream outputStream = new FileOutputStream(filePath)) {
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
}
}
При работе с большими объемами данных или потоковой обработкой можно использовать более эффективный подход:
private void processLargeResponse(HttpURLConnection connection,
Consumer<String> lineProcessor) throws IOException {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(connection.getInputStream()))) {
String line;
while ((line = reader.readLine()) != null) {
// Обработка каждой строки по мере её чтения
lineProcessor.accept(line);
}
}
}
// Пример использования:
processLargeResponse(connection, line -> {
// Обработка строки, например, парсинг JSON
if (line.contains("\"status\":\"error\"")) {
System.out.println("Found error in response");
}
});
Для обработки ответов в формате JSON часто используются специализированные библиотеки, такие как Jackson или Gson. Вот пример с использованием Gson:
import com.google.gson.Gson;
import com.google.gson.JsonObject;
// ...
private JsonObject parseJsonResponse(HttpURLConnection connection) throws IOException {
try (BufferedReader reader = new BufferedReader(
new InputStreamReader(connection.getInputStream()))) {
Gson gson = new Gson();
return gson.fromJson(reader, JsonObject.class);
}
}
// Использование:
JsonObject json = parseJsonResponse(connection);
String status = json.get("status").getAsString();
int count = json.get("count").getAsInt();
При обработке ошибок важно читать содержимое ответа из правильного потока:
private String readResponse(HttpURLConnection connection) throws IOException {
InputStream stream;
if (connection.getResponseCode() >= 400) {
stream = connection.getErrorStream();
} else {
stream = connection.getInputStream();
}
try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) {
StringBuilder response = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
response.append(line);
}
return response.toString();
}
}
Для потоковой обработки очень больших ответов можно использовать подход с ограниченным буфером:
public void processStreamingData(String urlString,
Consumer<String> chunkProcessor) throws IOException {
URL url = new URL(urlString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
try (InputStream in = connection.getInputStream();
InputStreamReader inReader = new InputStreamReader(in);
BufferedReader buffReader = new BufferedReader(inReader)) {
char[] buffer = new char[8192]; // 8KB буфер
int charsRead;
while ((charsRead = buffReader.read(buffer)) != -1) {
String chunk = new String(buffer, 0, charsRead);
chunkProcessor.accept(chunk);
}
} finally {
connection.disconnect();
}
}
При работе с ответами API следует также обратить внимание на следующие аспекты:
- Кодировка: Используйте правильную кодировку при чтении текста (UTF-8 в большинстве случаев)
- Сжатие: Обрабатывайте сжатые ответы (gzip, deflate), если сервер их поддерживает
- Тайм-ауты: Устанавливайте разумные тайм-ауты для чтения данных
- Прогресс: Отслеживайте прогресс загрузки для длительных операций
- Валидация: Проверяйте корректность полученных данных
Для обработки сжатых ответов можно использовать классы GZIPInputStream или InflaterInputStream:
// Установка заголовка для запроса сжатого контента
connection.setRequestProperty("Accept-Encoding", "gzip, deflate");
// Чтение сжатого ответа
InputStream inputStream;
String encoding = connection.getContentEncoding();
if ("gzip".equals(encoding)) {
inputStream = new GZIPInputStream(connection.getInputStream());
} else if ("deflate".equals(encoding)) {
inputStream = new InflaterInputStream(connection.getInputStream());
} else {
inputStream = connection.getInputStream();
}
// Теперь читаем из inputStream как обычно
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
// ...
Работа с URLConnection в Java может показаться сложной и многословной, особенно на фоне современных HTTP-клиентов, но понимание этого базового API открывает доступ к контролю над всеми аспектами HTTP-взаимодействия. Вы теперь знаете, как устанавливать соединения, отправлять различные типы запросов, управлять заголовками и эффективно обрабатывать ответы. Владение этими навыками не только поможет в поддержке легаси-кода, но и даст глубокое понимание HTTP-протокола, что критически важно даже при использовании высокоуровневых библиотек. Следующим шагом может стать изучение HttpClient из Java 11+, который сочетает удобство современных API с мощью встроенных решений.