0Pricing
Java Academy · Урок

Обработка ошибок и асинхронный конвейер HTTP

Обрабатывайте ошибки с помощью exceptionally, handle и whenComplete, а затем создавайте асинхронный конвейер HTTP-клиента.

«Обработка ошибок и асинхронный конвейер HTTP» — бесплатный урок Java Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Java Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Java Academy содержит 4 уроков всего.

Почему важна обработка асинхронных ошибок

В асинхронных конвейерах исключения распространяются не так, как в синхронном коде. Необходимо явно обрабатывать ошибки с помощью exceptionally, handle или whenComplete.

exceptionally: Восстановление после ошибок

exceptionally(Function<Throwable, T>) вызывается только в том случае, если future завершается с исключением. Он предоставляет резервное значение, позволяя конвейеру продолжить работу.

CompletableFuture<String> safe = fetchUser(id)
    .thenApply(User::getName)
    .exceptionally(ex -> {
        log.warn("Fetch failed: " + ex.getMessage());
        return "Anonymous";
    });
System.out.println(safe.join()); // "Anonymous" if fetch failed

handle: Преобразование успешного результата и ошибки

handle(BiFunction<T, Throwable, U>) вызывается как при успешном завершении, так и при ошибке. Один из двух аргументов будет равен null.

fetchUser(id).handle((user, ex) -> {
    if (ex != null) return UserDto.empty();
    return UserDto.from(user);
}).thenAccept(dto -> sendResponse(dto));

whenComplete: Побочный эффект после любого результата

whenComplete(BiConsumer) вызывается после завершения независимо от результата. Он не изменяет результат — используйте его для журналирования, сбора метрик или очистки.

fetchUser(id)
    .whenComplete((user, ex) -> {
        if (ex != null) metrics.increment("user.fetch.error");
        else            metrics.increment("user.fetch.success");
    })
    .thenAccept(u -> sendResponse(u));

Повторные попытки для завершившихся ошибкой future

Реализуйте логику повторных попыток, рекурсивно вызывая операцию при ошибке, пока не будет достигнуто максимальное число попыток.

CompletableFuture<String> withRetry(Supplier<CompletableFuture<String>> task, int retries) {
    return task.get().exceptionallyCompose(ex -> {
        if (retries > 0) {
            System.out.println("Retrying... " + retries);
            return withRetry(task, retries - 1);
        }
        return CompletableFuture.failedFuture(ex);
    });
}

Java 11 HttpClient: Асинхронный GET

В Java 11 HttpClient предоставляет полностью асинхронный HTTP через sendAsync(), возвращая CompletableFuture<HttpResponse<String>>.

HttpClient client = HttpClient.newHttpClient();
HttpRequest req = HttpRequest.newBuilder()
    .uri(URI.create("https://api.example.com/users/1"))
    .build();
CompletableFuture<String> body = client
    .sendAsync(req, HttpResponse.BodyHandlers.ofString())
    .thenApply(HttpResponse::body);

Цепочка нескольких HTTP-вызовов

Используйте thenCompose, чтобы объединить зависимые HTTP-вызовы в цепочку: сначала получите пользователя, затем используйте его ID, чтобы получить заказы этого пользователя.

client.sendAsync(userReq, HttpResponse.BodyHandlers.ofString())
    .thenApply(r -> parseUser(r.body()))
    .thenCompose(user -> client.sendAsync(
        buildOrdersRequest(user.getId()),
        HttpResponse.BodyHandlers.ofString()))
    .thenApply(r -> parseOrders(r.body()))
    .thenAccept(orders -> System.out.println("Orders: " + orders.size()));

Параллельные HTTP-вызовы с allOf

Отправьте запросы к нескольким конечным точкам параллельно, а затем соберите все ответы после их завершения.

List<URI> endpoints = List.of(uri1, uri2, uri3);
List<CompletableFuture<String>> requests = endpoints.stream()
    .map(uri -> client.sendAsync(
            HttpRequest.newBuilder(uri).build(),
            HttpResponse.BodyHandlers.ofString())
        .thenApply(HttpResponse::body))
    .collect(Collectors.toList());
List<String> responses = CompletableFuture
    .allOf(requests.toArray(new CompletableFuture[0]))
    .thenApply(v -> requests.stream().map(CompletableFuture::join).collect(Collectors.toList()))
    .join();

Тайм-аут HTTP-вызовов

Примените orTimeout непосредственно к асинхронному HTTP-вызову, чтобы отменить его, если сервер отвечает слишком долго.

CompletableFuture<String> result = client
    .sendAsync(req, HttpResponse.BodyHandlers.ofString())
    .orTimeout(5, TimeUnit.SECONDS)
    .thenApply(HttpResponse::body)
    .exceptionally(ex -> "timeout or error");

Проверка кода состояния в конвейере

Используйте thenApply, чтобы проверить код состояния HTTP и выбросить исключение предметной области, если он указывает на ошибку, сохраняя единообразную обработку ошибок в конвейере.

.thenApply(response -> {
    if (response.statusCode() != 200)
        throw new HttpResponseException(response.statusCode());
    return response.body();
})

Сочетание восстановления после ошибок и журналирования

Добавьте whenComplete для журналирования и exceptionally для восстановления в одном конвейере — они легко объединяются.

fetchData()
    .whenComplete((r, ex) -> { if (ex != null) log.error("Failed", ex); })
    .exceptionally(ex -> fallback())
    .thenAccept(result -> process(result));

Быстрая проверка

Какой метод CompletableFuture вызывается ONLY при сбое future?

Повторение

Используйте exceptionally для резервных значений, handle для преобразования обоих результатов, а whenComplete — для побочных эффектов. Создавайте асинхронные HTTP-конвейеры с помощью Java 11 HttpClient + thenCompose + allOf.

Часто задаваемые вопросы

Урок «Обработка ошибок и асинхронный конвейер HTTP» бесплатный?

Да — полный текст урока «Обработка ошибок и асинхронный конвейер HTTP» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Java Academy, подпишись на CoddyKit PRO. Курс Java Academy содержит 4 уроков всего.

Чему я научусь в уроке «Обработка ошибок и асинхронный конвейер HTTP»?

Обрабатывайте ошибки с помощью exceptionally, handle и whenComplete, а затем создавайте асинхронный конвейер HTTP-клиента. Ты практикуешь Java Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Java Academy?

Предыдущий опыт не требуется. Java Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Обработка ошибок и асинхронный конвейер HTTP»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Java Academy?

Да. Каждый урок Java Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Создание и завершение CompletableFutures
  2. Объединение thenApply и thenCompose в цепочки
  3. Объединение будущих объектов: allOf и anyOf
  4. Обработка ошибок и асинхронный конвейер HTTP
← Назад к Java Academy