1.1 Знакомство с HttpClient
Начиная с JDK 11 разработчики платформы Java добавили в JDK новый мощный инструмент для выполнения http-запросов — пакет java.net.http
. Он содержит четыре ключевых класса:
- HttpClient
- HttpRequest
- HttpResponse
- WebSocket
Это очень мощные классы, которые позволяют выполнять все возможные виды запросов по протоколам HTTP
, HTTP/2
и WebSocket
.
Кроме того, с помощью этих классов можно выполнять как синхронные, так и асинхронные http-запросы.
Выполнение http-запроса состоит из таких частей:
- Создание объекта
HttpClient
- Создание объекта
HttpRequеst
- Отправка запроса с помощью метода
send()
илиsendAsync()
- Обработка ответа
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
возвращают свой же объект, что позволяет организовать код в виде цепочек.
Классический код: |
---|
|
В виде цепочки: |
|
Переносим каждый метод на отдельную строку (это один длинный statement) |
|
Во-вторых, у методов убирают префикс set
, что позволяет писать код еще компактнее:
Было |
---|
|
Стало |
|
Такой код проще читать, хотя сложнее писать.
И еще один важный момент. В этом примере использовался шаблон (pattern) Builder. Бывают сценарии, когда создание объекта — это сложный процесс. Поэтому его предпочитают формализовать: он начинается с вызова условного метода begin()
и заканчивается вызовом условного метода end()
.
В примере, который мы разбирали, метод HttpClient.newBuilder()
возвращает объект HttpClient.Builder
(это внутренний служебный класс у класса HttpClient
). Все методы типа version()
вызываются как раз у этого служебного объекта. Ну а вызов метода build()
обозначает окончание построения объекта и возвращает объект HttpClient
.