1. Обзор
В этом руководстве мы покажем, как настроить тайм-аут с новым HTTP-клиентом Java, доступным, начиная с Java 11, и пакетом Java.
Если нам нужно освежить наши знания, мы можем начать с учебника по HTTP-клиенту Java .
С другой стороны, чтобы узнать, как настроить тайм-аут с помощью старой библиотеки, см . HttpUrlConnection.
2. Настройка тайм-аута
Прежде всего, нам нужно настроить HttpClient, чтобы иметь возможность делать HTTP-запросы:
private static HttpClient getHttpClientWithTimeout(int seconds) {
return HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(seconds))
.build();
}
Выше мы создали метод, который возвращает HttpClient
, настроенный с тайм-аутом, определенным в качестве параметра. Вкратце, мы используем шаблон проектирования Builder для создания экземпляра HttpClient
и настройки времени ожидания с помощью метода connectTimeout
. Кроме того, с помощью статического метода ofSeconds
мы создали экземпляр объекта Duration
, который определяет время ожидания в секундах.
После этого проверяем, правильно ли настроен таймаут HttpClient
:
httpClient.connectTimeout().map(Duration::toSeconds)
.ifPresent(sec -> System.out.println("Timeout in seconds: " + sec));
Итак, мы используем метод connectTimeout
для получения времени ожидания. В результате он возвращает необязательный
параметр Duration,
который мы сопоставили с секундами.
3. Обработка тайм-аутов
Далее нам нужно создать объект HttpRequest
, который наш клиент будет использовать для выполнения HTTP-запроса:
HttpRequest httpRequest = HttpRequest.newBuilder()
.uri(URI.create("http://10.255.255.1")).GET().build();
Чтобы имитировать тайм-аут, мы делаем вызов на немаршрутизируемый IP-адрес. Другими словами, все TCP-пакеты отбрасываются и вызывают тайм-аут по истечении предопределенного времени, настроенного ранее.
Теперь давайте подробнее рассмотрим, как обрабатывать тайм-аут.
3.1. Обработка тайм-аута синхронного вызова
Например, чтобы сделать синхронный вызов, используйте метод send
:
HttpConnectTimeoutException thrown = assertThrows(
HttpConnectTimeoutException.class,
() -> httpClient.send(httpRequest, HttpResponse.BodyHandlers.ofString()),
"Expected send() to throw HttpConnectTimeoutException, but it didn't");
assertTrue(thrown.getMessage().contains("timed out"));
Синхронный вызов заставляет перехватывать исключение IOException
, которое расширяет исключение HttpConnectTimeoutException
. Следовательно, в приведенном выше тесте мы ожидаем HttpConnectTimeoutException
с сообщением об ошибке.
3.2. Обработка времени ожидания асинхронного вызова
Точно так же, чтобы сделать асинхронный вызов, используйте метод sendAsync
:
CompletableFuture<String> completableFuture = httpClient.sendAsync(httpRequest, HttpResponse.BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.exceptionally(Throwable::getMessage);
String response = completableFuture.get(5, TimeUnit.SECONDS);
assertTrue(response.contains("timed out"));
Приведенный выше вызов sendAsync
возвращает CompletableFuture<HttpResponse>
. Следовательно, нам нужно определить, как функционально обрабатывать ответ. Подробно, мы получаем тело из ответа, когда ошибок не возникает. В противном случае мы получим сообщение об ошибке от throwable. Наконец, мы получаем результат от CompletableFuture
, подождав максимум 5 секунд. Опять же, этот запрос вызывает исключение HttpConnectTimeoutException
, как мы и ожидали, сразу после 3 секунд.
4. Настройте тайм-аут на уровне запроса
Выше мы повторно использовали один и тот же экземпляр клиента как для синхронизации
, так и для асинхронного
вызова. Однако мы можем захотеть обрабатывать тайм-аут по-разному для каждого запроса. Точно так же мы можем настроить тайм-аут для одного запроса:
HttpRequest httpRequest = HttpRequest.newBuilder()
.uri(URI.create("http://10.255.255.1"))
.timeout(Duration.ofSeconds(1))
.GET()
.build();
Точно так же мы используем метод тайм
-аута , чтобы установить тайм-аут для этого запроса. Здесь мы настроили тайм-аут в 1 секунду для этого запроса.
Минимальная продолжительность между клиентом и запросом устанавливает время ожидания для запроса.
5. Выводы
В этой статье мы успешно настроим тайм-аут с помощью нового HTTP-клиента Java и изящно обработаем запрос, когда тайм-ауты переполнятся.
И, как всегда, исходный код примеров доступен на GitHub .