HttpRequest.Builder.build: примеры (JAVA)
HttpRequest.Builder.build: HttpRequestКраткое описание метода
Метод HttpRequest.Builder.build() создает окончательный неизменяемый объект java.net.http.HttpRequest на основе текущего состояния билдера. Вызов применяется после задания необходимых параметров запроса и возвращает готовый экземпляр, пригодный для отправки через HttpClient.
public abstract HttpRequest build()
Аргументы: отсутствуют. Метод использует внутреннее состояние билдера, которое формируется вызовами таких методов, как uri(URI), header(String,String), headers(String...), GET(), POST(HttpRequest.BodyPublisher), method(String, BodyPublisher), timeout(Duration), version(HttpClient.Version), expectContinue(boolean) и др.
Возвращаемое значение: готовый объект HttpRequest, представляющий HTTP-запрос. Полученный объект неизменяемый; повторные вызовы build() на одном билдере допускаются и создают отдельные объекты с текущим состоянием.
Поведение и детали:
- URI: требование наличия URI при сборке. Отсутствие URI обычно приводит к исключению (см. раздел ошибок).
- Метод: если явно не установлен, фактическое значение определяется состоянием билдера. При отсутствии явного метода и при отсутствии тела по умолчанию применяется поведение аналогичное GET. Для отправки тела используются POST, PUT или method(...).
- Тело: если не задан BodyPublisher, по умолчанию используется публикация без тела (BodyPublishers.noBody()).
- Заголовки: можно добавлять через
headerилиheaders. Повторяющиеся заголовки сохраняются в порядке добавления. - Версия протокола: если не указана, решение о версии выполняет
HttpClient. Билдер хранит предпочтение версии при вызовеversion(...). - Ожидание продолжения: поддержка механизма Expect: 100-continue через
expectContinue(true).
Исключения, которые могут возникнуть при вызове build(): IllegalStateException при отсутствии обязательных данных (например, URI), IllegalArgumentException в случае некорректных значений (например, пустое имя метода), NullPointerException при передаче явно недопустимых null в методы билдера. Точные виды исключений зависят от состояния билдера и версий JDK.
Примеры базового применения
Ниже приведены короткие примеры создания запросов. Каждый пример содержит код и ожидаемый вывод при выполнении кода в типичной среде.
1. Простой GET без отправки
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://example.com/"))
.GET()
.build();
System.out.println(request.method());
System.out.println(request.uri());
GET https://example.com/
2. POST с JSON и синхронной отправкой
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://httpbin.org/post"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString("{\"name\":\"Alice\"}"))
.build();
HttpResponse resp = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(resp.statusCode());
System.out.println(resp.body().substring(0, 80) + "...");
200
{"args":{},"data":"{\"name\":\"Alice\"}","files":{},"form":...}
3. Пользовательский метод PATCH
HttpRequest req = HttpRequest.newBuilder()
.uri(URI.create("https://httpbin.org/patch"))
.method("PATCH", HttpRequest.BodyPublishers.ofString("field=value"))
.build();
System.out.println(req.method());
System.out.println(req.bodyPublisher().isPresent());
PATCH true
4. Отправка файла (без фактической отправки в примере кода)
Path file = Paths.get("/path/to/file.bin");
HttpRequest r = HttpRequest.newBuilder()
.uri(URI.create("https://example.com/upload"))
.POST(HttpRequest.BodyPublishers.ofFile(file))
.build();
System.out.println(r.bodyPublisher().isPresent());
true
Аналоги внутри Java и различия
В экосистеме Java есть несколько подходов к формированию HTTP-запросов. Краткое сравнение:
- java.net.HttpURLConnection - старый встроенный API. Менее удобен, вручную управляет потоками и заголовками, но не требует внешних зависимостей.
- Apache HttpClient (CloseableHttpClient) - богатый функционал, расширенные возможности конфигурации и совместимость со старыми версиями Java; предпочтительнее при сложных требованиях к прокси и соединениям.
- OkHttp - популярная библиотека с простым билдером запросов, эффективной реализацией HTTP/2 и кэшированием; часто выбирается в клиентских приложениях и Android.
- JAX-RS Client и Spring RestTemplate/WebClient - более высокоуровневые абстракции, полезны при интеграции с REST-сервисами и при работе в контейнерах. WebClient обеспечивает реактивную модель.
Выбор зависит от требований: для простоты и интеграции с JDK предпочтителен java.net.http, при необходимости расширенных опций соединения или кросс-платформенной совместимости стоит рассматривать внешние библиотеки.
Аналоги в других языках и особенности
Ниже краткие примеры создания аналогичных HTTP-запросов в популярных языках с указанием отличий.
PHP (curl)
$ch = curl_init('https://httpbin.org/post');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['name' => 'Alice']));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$resp = curl_exec($ch);
curl_close($ch);
var_dump(substr($resp,0,80));
string(80) "{\n \"args\": {}, \n \"data\": \"{\"name\":\"Alice\"}\","
JavaScript (Fetch)
fetch('https://httpbin.org/post', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({name: 'Alice'})
}).then(r => r.text()).then(t => console.log(t.slice(0,80)));
{"args":{},"data":"{"name":"Alice"}","files":{},"form":...}
Python (requests)
import requests
r = requests.post('https://httpbin.org/post', json={'name':'Alice'})
print(r.status_code)
print(r.text[:80])
200
{"args":{},"data":"{\"name\":\"Alice\"}","files":{},"form":...}
C# (.NET HttpClient)
using var client = new HttpClient();
var resp = await client.PostAsync("https://httpbin.org/post",
new StringContent("{\"name\":\"Alice\"}", Encoding.UTF8, "application/json"));
Console.WriteLine((int)resp.StatusCode);
Console.WriteLine((await resp.Content.ReadAsStringAsync()).Substring(0,80));
200
{"args":{},"data":"{\"name\":\"Alice\"}","files":{},"form":...}
Go (net/http)
req, _ := http.NewRequest("POST", "https://httpbin.org/post", strings.NewReader(`{"name":"Alice"}`))
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
b, _ := io.ReadAll(resp.Body)
fmt.Println(resp.StatusCode)
fmt.Println(string(b)[:80])
200
{"args":{},"data":"{\"name\":\"Alice\"}","files":{},"form":...}
Lua (lua-http / luasocket)
local http = require('socket.http')
local ltn12 = require('ltn12')
local body = {}
local res, code = http.request{
url = 'https://httpbin.org/post',
method = 'POST',
headers = {['Content-Type']='application/json'},
source = ltn12.source.string('{"name":"Alice"}'),
sink = ltn12.sink.table(body)
}
print(code)
print(table.concat(body):sub(1,80))
200
{"args":{},"data":"{\"name\":\"Alice\"}","files":{},"form":...}
Отличия от Java: в большинстве языков создание и отправка запроса объединены в один вызов или в простую цепочку вызовов. Java HttpRequest.Builder отделяет построение запроса и отправку, что упрощает тестирование и повторное использование конфигурации.
Типичные ошибки и их проявления
Ниже описаны распространенные ошибки при вызове build() с примерами и результатом.
1. Отсутствие URI
HttpRequest req = HttpRequest.newBuilder()
.GET()
.build();
Exception in thread "main" java.lang.IllegalStateException: request URI not set
at jdk.httpclient/... (stack trace)
2. Некорректное имя метода
HttpRequest.newBuilder()
.uri(URI.create("https://example.com"))
.method("", HttpRequest.BodyPublishers.noBody())
.build();
Exception in thread "main" java.lang.IllegalArgumentException: invalid HTTP method name
at jdk.httpclient/... (stack trace)
3. Попытка передать null в методы билдера
HttpRequest.newBuilder()
.uri(null)
.build();
Exception in thread "main" java.lang.NullPointerException
at java.base/... (stack trace)
Рекомендации по диагностике: проверка наличия URI перед сборкой, валидация имени метода, использование безопасных фабрик BodyPublishers и обработка возможных исключений в коде, формирующем запрос.
Изменения и история
Класс HttpRequest и вложенный интерфейс/билдер появились в JDK 11 вместе с java.net.http.HttpClient. С тех пор сигнатура build() осталась стабильной. Основные изменения в экосистеме касались транспорта и возможностей клиента: добавление улучшенной поддержки HTTP/2 и экспериментальная поддержка HTTP/3 в более поздних релизах JDK. Эти изменения влияли на поведение HttpClient и на способы управления версией через version(HttpClient.Version), но метод build() не претерпел существенных изменений.
Расширенные и редкие сценарии использования
Несколько подробных примеров, которые демонстрируют нестандартные и продвинутые случаи применения билдера.
1. Повторное использование билдера для серии запросов
HttpRequest.Builder b = HttpRequest.newBuilder()
.header("User-Agent", "MyClient/1.0")
.timeout(Duration.ofSeconds(10));
HttpRequest r1 = b.uri(URI.create("https://example.com/a")).GET().build();
HttpRequest r2 = b.uri(URI.create("https://example.com/b")).POST(HttpRequest.BodyPublishers.ofString("x=1")).build();
System.out.println(r1.uri());
System.out.println(r2.method());
https://example.com/a POST
2. Потоковая отправка большого файла
Path big = Paths.get("/data/large.bin");
HttpRequest r = HttpRequest.newBuilder()
.uri(URI.create("https://upload.example.com/"))
.timeout(Duration.ofMinutes(5))
.POST(HttpRequest.BodyPublishers.ofFile(big))
.build();
// при отправке HttpClient будет считывать файл по мере передачи, что экономит память
(при отправке: возможен длительный процесс; build не производит чтение файла)
3. Асинхронная отправка и комбинирование ответов
HttpClient client = HttpClient.newHttpClient();
HttpRequest r = HttpRequest.newBuilder()
.uri(URI.create("https://httpbin.org/get"))
.build();
client.sendAsync(r, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(b -> System.out.println(b.substring(0,80)));
{"args":{},"headers":{...},"origin":"...","url":"https://httpbin.org/get"...}
4. Использование Flow.Publisher для реактивной передачи тела
Flow.Publisher publisher = new Flow.Publisher<>() {
public void subscribe(Flow.Subscriber<? super ByteBuffer> s) {
s.onSubscribe(new Flow.Subscription() {
public void request(long n) { s.onNext(ByteBuffer.wrap("chunk".getBytes())); s.onComplete(); }
public void cancel() { }
});
}
};
HttpRequest r = HttpRequest.newBuilder()
.uri(URI.create("https://example.com/stream"))
.method("POST", HttpRequest.BodyPublishers.ofPublisher(publisher))
.build();
System.out.println(r.bodyPublisher().isPresent());
true
5. Expect: 100-continue и таймауты
HttpRequest r = HttpRequest.newBuilder()
.uri(URI.create("https://example.com/upload"))
.expectContinue(true)
.timeout(Duration.ofSeconds(30))
.POST(HttpRequest.BodyPublishers.ofString("payload"))
.build();
System.out.println(r.expectContinue());
System.out.println(r.timeout().get().getSeconds());
true 30
6. Установка предпочтительной версии HTTP
HttpRequest r = HttpRequest.newBuilder()
.uri(URI.create("https://example.com"))
.version(HttpClient.Version.HTTP_2)
.build();
System.out.println(r.version().get());
HTTP_2
Пояснения: большинство операций билдера не выполняют сетевых действий. Метод build() лишь формирует объект запроса. Это позволяет выполнять тестирование и подготовку запросов без сетевых вызовов, а также повторно применять шаблоны конфигурации.
джава HttpRequest.Builder.build function comments
- джава HttpRequest.Builder.build - аргументы и возвращаемое значение
- Функция java HttpRequest.Builder.build - описание
- HttpRequest.Builder.build - примеры
- HttpRequest.Builder.build - похожие методы на java
- HttpRequest.Builder.build на javascript, c#, python, php
- HttpRequest.Builder.build изменения java
- Примеры HttpRequest.Builder.build на джава