java.net.URLConnection: как работать с HTTP запросами и ответами

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

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

Начать курс

Введение: почему URLConnection — это must know для Java-разработчика

Вы когда-нибудь задумывались, как ваш любимый браузер или мобильное приложение общается с сервером? Волшебство скрывается в простых, но мощных HTTP-запросах. И в Java для этого есть свой «швейцарский нож» — класс java.net.URLConnection.

Несмотря на то, что в Java 11 появился новый модульный HttpClient, тысячи разработчиков по всему миру продолжают использовать старый добрый URLConnection. Почему? Во-первых, это legacy-код, который нужно поддерживать. Во-вторых, он простой и не требует сторонних библиотек. А в-третьих, понимание того, как работают HTTP-запросы на низком уровне, делает вас настоящим профи.

В этой статье мы не просто скопируем ответ со Stack Overflow. Мы разберем два подхода к работе с URLConnection и сравним их с современным HttpClient. Вы узнаете, как отправлять GET и POST запросы, обрабатывать ошибки, устанавливать заголовки и читать ответы сервера. Поехали!

Что такое java.net.URLConnection и зачем он нужен?

Класс java.net.URLConnection — это абстрактный класс, который представляет собой активное соединение с ресурсом, указанным в URL. Простыми словами: это мостик между вашим Java-приложением и сервером в интернете. Он умеет:

  • Открывать соединение с сервером
  • Отправлять данные (GET, POST, PUT, DELETE)
  • Читать ответ сервера
  • Управлять заголовками запроса и ответа
  • Работать с куками

Но есть нюанс: URLConnection не делает ничего сам. Он лишь предоставляет механизм. Всю магию делают его подклассы — например, HttpURLConnection для работы с HTTP.

Подход 1: Классический способ с HttpURLConnection (проверено временем)

Этот метод использовали наши отцы-основатели Java-программирования. Он надежен, но требует ручной работы. Давайте разберем его на примере GET-запроса.

Пример 1: GET-запрос с обработкой ответа

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class GetRequestExample {
    public static void main(String[] args) throws Exception {
        // 1. Создаем URL объект
        URL url = new URL("https://api.github.com/users/octocat");
        
        // 2. Открываем соединение
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        
        // 3. Настраиваем запрос
        connection.setRequestMethod("GET");
        connection.setRequestProperty("User-Agent", "Mozilla/5.0");
        connection.setConnectTimeout(5000);
        connection.setReadTimeout(5000);
        
        // 4. Проверяем код ответа
        int responseCode = connection.getResponseCode();
        System.out.println("Response Code: " + responseCode);
        
        // 5. Читаем тело ответа
        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 Body: " + response.toString());
        } else {
            System.out.println("GET request failed");
        }
        
        // 6. Закрываем соединение
        connection.disconnect();
    }
}

Разбор кода:

  • setRequestMethod — задает HTTP-метод (GET, POST, PUT, DELETE)
  • setRequestProperty — устанавливает заголовки (User-Agent, Content-Type и т.д.)
  • getResponseCode() — получает код состояния HTTP (200, 404, 500)
  • getInputStream() — читает тело ответа сервера
  • disconnect() — закрывает соединение

Пример 2: POST-запрос с отправкой данных

А теперь усложним задачу. Допустим, нужно отправить JSON на сервер. Для этого используем POST-запрос.

import java.io.OutputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class PostRequestExample {
    public static void main(String[] args) throws Exception {
        URL url = new URL("https://jsonplaceholder.typicode.com/posts");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        
        // Настройка POST-запроса
        connection.setRequestMethod("POST");
        connection.setRequestProperty("Content-Type", "application/json; utf-8");
        connection.setRequestProperty("Accept", "application/json");
        connection.setDoOutput(true); // Включаем возможность отправки данных
        
        // Тело запроса (JSON)
        String jsonInputString = "{\"title\": \"foo\", \"body\": \"bar\", \"userId\": 1}";
        
        // Отправляем данные
        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);
        
        BufferedReader in = new BufferedReader(
            new InputStreamReader(connection.getInputStream(), "utf-8"));
        StringBuilder response = new StringBuilder();
        String responseLine;
        
        while ((responseLine = in.readLine()) != null) {
            response.append(responseLine.trim());
        }
        
        System.out.println("Response Body: " + response.toString());
        connection.disconnect();
    }
}

Ключевые моменты:

  • setDoOutput(true) — обязательно для отправки данных (POST, PUT)
  • getOutputStream() — используется для записи тела запроса
  • Всегда указывайте Content-Type, чтобы сервер знал, как интерпретировать данные

Подход 2: Современный HttpClient (Java 11+)

Начиная с Java 11, в стандартной библиотеке появился java.net.http.HttpClient. Он более гибкий, поддерживает асинхронные запросы и не требует ручного управления потоками. Сравним с классикой.

GET-запрос с HttpClient

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

public class ModernGetExample {
    public static void main(String[] args) throws Exception {
        HttpClient client = HttpClient.newHttpClient();
        
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://api.github.com/users/octocat"))
                .header("User-Agent", "Mozilla/5.0")
                .GET()
                .build();
        
        HttpResponse response = client.send(request, 
            HttpResponse.BodyHandlers.ofString());
        
        System.out.println("Response Code: " + response.statusCode());
        System.out.println("Response Body: " + response.body());
    }
}

POST-запрос с HttpClient

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 json = "{\"title\": \"foo\", \"body\": \"bar\", \"userId\": 1}";
        
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI                

Блоги

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