Какие основные способы выполнения HTTP-запросов в Java?

«Какие основные способы выполнения HTTP-запросов в Java?» — вопрос из категории Сети, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В Java существует несколько стандартных и библиотечных способов выполнения HTTP-запросов, от низкоуровневых до высокоуровневых абстракций.

1. Java 11+ HttpClient (Стандартный, асинхронный/синхронный) Современный API, поддерживающий HTTP/2 и WebSocket.

// Синхронный GET-запрос
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-запрос с JSON
String json = "{"name":"John"}";
HttpRequest postRequest = HttpRequest.newBuilder()
      .uri(URI.create("https://api.example.com/users"))
      .header("Content-Type", "application/json")
      .POST(HttpRequest.BodyPublishers.ofString(json))
      .build();
client.sendAsync(postRequest, HttpResponse.BodyHandlers.ofString())
      .thenApply(HttpResponse::body)
      .thenAccept(System.out::println);

2. Spring RestTemplate (Синхронный, устаревший в пользу WebClient)

RestTemplate restTemplate = new RestTemplate();
String url = "https://api.example.com/users/{id}";
User user = restTemplate.getForObject(url, User.class, 1); // GET
ResponseEntity<User> response = restTemplate.getForEntity(url, User.class, 1);

// POST
User newUser = new User("Jane");
User createdUser = restTemplate.postForObject("https://api.example.com/users", newUser, User.class);

3. Spring WebClient (Реактивный, асинхронный, рекомендованный)

WebClient client = WebClient.create("https://api.example.com");
Mono<User> userMono = client.get()
      .uri("/users/{id}", 1)
      .header("Authorization", "Bearer token")
      .retrieve()
      .bodyToMono(User.class);

userMono.subscribe(user -> System.out.println(user.getName()));

// POST с телом
Mono<User> createdUser = client.post()
      .uri("/users")
      .contentType(MediaType.APPLICATION_JSON)
      .bodyValue(new User("Bob"))
      .retrieve()
      .bodyToMono(User.class);

4. Библиотеки третьих сторон

  • Apache HttpClient: Мощный и гибкий клиент.
  • OkHttp: Эффективный клиент от Square, часто используется с Retrofit.
  • Retrofit + OkHttp: Типобезопасный REST-клиент для Android и Java, генерирует реализации интерфейсов.

Критерии выбора:

  • Синхронность/Асинхронность: HttpClient/WebClient для неблокирующих вызовов.
  • Экосистема: В Spring-проектах предпочтителен WebClient.
  • Сложность: HttpClient требует больше boilerplate-кода, WebClient и RestTemplate предоставляют более высокоуровневый API.