JavaRush /Курсы /JSP & Servlets /Новый HttpClient

Новый HttpClient

JSP & Servlets
10 уровень , 0 лекция
Открыта

1.1 Знакомство с HttpClient

Начиная с JDK 11 разработчики платформы Java добавили в JDK новый мощный инструмент для выполнения http-запросов — пакет java.net.http. Он содержит четыре ключевых класса:

  • HttpClient
  • HttpRequest
  • HttpResponse
  • WebSocket

Это очень мощные классы, которые позволяют выполнять все возможные виды запросов по протоколам HTTP, HTTP/2 и WebSocket.

Кроме того, с помощью этих классов можно выполнять как синхронные, так и асинхронные http-запросы.

Выполнение http-запроса состоит из таких частей:

  1. Создание объекта HttpClient
  2. Создание объекта HttpRequеst
  3. Отправка запроса с помощью метода send() или sendAsync()
  4. Обработка ответа HttpResponse

Пример такого запроса:


 HttpClient client = HttpClient.newBuilder()
        .version(Version.HTTP_1_1)
        .followRedirects(Redirect.NORMAL)
        .connectTimeout(Duration.ofSeconds(20))
        .proxy(ProxySelector.of(new InetSocketAddress("proxy.example.com", 80)))
        .authenticator(Authenticator.getDefault())
        .build();
 
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body()); 

1.2 Декларативный подход

В примере выше ты наблюдаешь пример так называемого декларативного подхода к написанию кода. Давай разберем первую часть примера:


 HttpClient client = HttpClient.newBuilder()
.version(Version.HTTP_1_1)
.followRedirects(Redirect.NORMAL)
.connectTimeout(Duration.ofSeconds(20))
.proxy(ProxySelector.of(new InetSocketAddress("proxy.example.com", 80)))
.authenticator(Authenticator.getDefault())
.build();

Как бы выглядел этот код, написанный в классическом стиле:


HttpClient client = HttpClient.new();
client.setVersion(Version.HTTP_1_1);
client.setFollowRedirects(Redirect.NORMAL);
client.setConnectTimeout(Duration.ofSeconds(20));
client.setProxy(ProxySelector.of(new InetSocketAddress("proxy.example.com", 80)));
client.setAuthenticator(Authenticator.getDefault());

При использовании декларативного подхода в коде меняются две вещи. Во-первых, все методы класса HttpClient возвращают свой же объект, что позволяет организовать код в виде цепочек.

Классический код:

HttpClient client = HttpClient.new();
client.setVersion(Version.HTTP_1_1);
client.setFollowRedirects(Redirect.NORMAL);
client.setConnectTimeout(Duration.ofSeconds(20));
client.setAuthenticator(Authenticator.getDefault());
В виде цепочки:

HttpClient client = HttpClient.new() .setVersion(Version.HTTP_1_1) .setFollowRedirects(Redirect.NORMAL). setConnectTimeout(Duration.ofSeconds(20)) .setAuthenticator(Authenticator.getDefault());
Переносим каждый метод на отдельную строку (это один длинный statement)

HttpClient client = HttpClient.new()
.setVersion(Version.HTTP_1_1)
.setFollowRedirects(Redirect.NORMAL)
.setConnectTimeout(Duration.ofSeconds(20))
.setAuthenticator(Authenticator.getDefault());

Во-вторых, у методов убирают префикс set, что позволяет писать код еще компактнее:

Было

HttpClient client = HttpClient.new()
.setVersion(Version.HTTP_1_1)
.setFollowRedirects(Redirect.NORMAL)
.setConnectTimeout(Duration.ofSeconds(20))
.setAuthenticator(Authenticator.getDefault());

Стало

HttpClient client = HttpClient.new()
.version(Version.HTTP_1_1)
.followRedirects(Redirect.NORMAL)
.connectTimeout(Duration.ofSeconds(20))
.authenticator(Authenticator.getDefault());
    

Такой код проще читать, хотя сложнее писать.

И еще один важный момент. В этом примере использовался шаблон (pattern) Builder. Бывают сценарии, когда создание объекта — это сложный процесс. Поэтому его предпочитают формализовать: он начинается с вызова условного метода begin() и заканчивается вызовом условного метода end().

В примере, который мы разбирали, метод HttpClient.newBuilder() возвращает объект HttpClient.Builder (это внутренний служебный класс у класса HttpClient). Все методы типа version() вызываются как раз у этого служебного объекта. Ну а вызов метода build() обозначает окончание построения объекта и возвращает объект HttpClient.

Комментарии (8)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Anonymous #3268884 Уровень 24
13 марта 2024
Некорректно написано: у методов убирают префикс set, что позволяет писать код еще компактнее. У метода нельзя просто отбросить часть названия, потому что это уже будет другой метод, и вызывать его нужно у объекта другого класса)) Поэтому в последнем примере в первой строке должно быть написано не HttpClient.new() а HttpClient.newBuilder() и все методы без слова set вызываются уже у объекта типа Билдер, а в конце добавляем метод .билд() и уже этот метод возвращает объект класса ХттпКлиент. Дополнительная задача на внимательность, чтобы студенты не спали.
hint1k Уровень 51
2 мая 2023
В примере пропущено создание объекта request. По идее должно быть что то типа такого:

        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://javarush.com"))
                .build();
P.s. пример оказывается написали на следующей странице. Типичная Джава Раш. Дать неработающий код, а потом на следующих страницах дать исправления/дополнения. Как же вы достали с таким подходом.
jvatechs Уровень 111 Expert
13 июня 2023
Все искал что-то подобное, тоже смекнул, что пропущен реквест. Спасибо!
Павел Уровень 19 Expert
26 декабря 2023
Добавил HttpRequest request, но код все равно не заработал.
Anonymous #3268884 Уровень 24
13 марта 2024
Я как только заметил эту фигню, сразу полез читать коменты. У Джава Раш много косяков в уроках, но они практически всегда исправлены самими учащимися в коментах. Такая типа интерактивность))
kv0ut Уровень 51
27 декабря 2022
То ли я не понял, то ли опечатка: "Выполнение http-запроса состоит из ТРЕХ частей:" после чего перечислены ЧЕТЫРЕ пункта
Oleg Уровень 41
7 ноября 2022
Здесь скорее паттерн билдер объясняется, чем http клиент)
YakovlevPA Уровень 86
13 июля 2022
В последнем стало вторая строка видимо лишняя)