0Pricing
Java Academy · Lekcja

Obsługa błędów i asynchroniczny potok HTTP

Obsługuj błędy za pomocą exceptionally, handle i whenComplete, a następnie zbuduj asynchroniczny potok klienta HTTP.

Obsługa błędów i asynchroniczny potok HTTP to bezpłatna lekcja Java Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Java Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Java Academy zawiera 4 lekcji w sumie.

Dlaczego obsługa błędów asynchronicznych ma znaczenie

W potokach asynchronicznych wyjątki nie są propagowane tak samo jak w kodzie synchronicznym. Błędy należy jawnie obsługiwać za pomocą exceptionally, handle lub whenComplete.

exceptionally: Odzyskiwanie po błędach

exceptionally(Function<Throwable, T>) jest wywoływana tylko wtedy, gdy future kończy się wyjątkiem. Dostarcza wartość zastępczą, dzięki czemu potok może działać dalej.

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: Przekształcanie powodzenia i błędu

handle(BiFunction<T, Throwable, U>) jest wywoływana zarówno po powodzeniu, jak i po błędzie. Jeden z dwóch argumentów będzie miał wartość null.

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

whenComplete: Efekt uboczny po dowolnym wyniku

whenComplete(BiConsumer) jest wywoływana po zakończeniu, niezależnie od wyniku. Nie zmienia wyniku — należy jej używać do rejestrowania logów, zbierania metryk lub sprzątania.

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

Ponawianie prób dla nieudanych obiektów Future

Logikę ponawiania prób należy zaimplementować, wywołując rekurencyjnie operację po wystąpieniu błędu, maksymalnie określoną liczbę razy.

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: asynchroniczne żądanie GET

HttpClient dostępny w Java 11 zapewnia w pełni asynchroniczną obsługę HTTP za pomocą sendAsync(), zwracając obiekt 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);

Łączenie wielu wywołań HTTP

Należy użyć thenCompose, aby połączyć zależne wywołania HTTP: najpierw pobrać użytkownika, a następnie użyć jego identyfikatora do pobrania zamówień.

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()));

Równoległe wywołania HTTP z użyciem allOf

Należy równolegle wysłać żądania do kilku punktów końcowych, a następnie zebrać wszystkie odpowiedzi po zakończeniu wszystkich operacji.

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();

Limit czasu wywołań HTTP

Należy zastosować orTimeout bezpośrednio do asynchronicznego wywołania HTTP, aby je anulować, jeśli serwer będzie odpowiadać zbyt długo.

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

Weryfikacja kodu statusu w potoku

Należy użyć thenApply, aby sprawdzić kod statusu HTTP i zgłosić wyjątek domenowy, jeśli wskazuje on na błąd. Dzięki temu obsługa błędów w potoku pozostaje spójna.

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

Łączenie odzyskiwania po błędach i rejestrowania logów

Należy użyć whenComplete do rejestrowania logów oraz exceptionally do odzyskiwania po błędach w tym samym potoku — te operacje dobrze się komponują.

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

Szybkie sprawdzenie

Która metoda CompletableFuture jest wywoływana TYLKO wtedy, gdy future zakończy się niepowodzeniem?

Podsumowanie

Należy używać exceptionally do dostarczania wartości zastępczych, handle do przekształcania obu wyników, a whenComplete do wykonywania efektów ubocznych. Asynchroniczne potoki HTTP można budować za pomocą Java 11 HttpClient, thenCompose i allOf.

Często zadawane pytania

Czy lekcja „Obsługa błędów i asynchroniczny potok HTTP” jest bezpłatna?

Tak — pełny tekst „Obsługa błędów i asynchroniczny potok HTTP” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Java Academy, przejdź na CoddyKit PRO. Kurs Java Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Obsługa błędów i asynchroniczny potok HTTP”?

Obsługuj błędy za pomocą exceptionally, handle i whenComplete, a następnie zbuduj asynchroniczny potok klienta HTTP. Ćwiczysz Java Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Java Academy?

Nie wymagamy żadnego doświadczenia. Java Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.

Ile czasu zajmuje lekcja „Obsługa błędów i asynchroniczny potok HTTP”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Java Academy?

Tak. Każda lekcja Java Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Tworzenie i uzupełnianie CompletableFuture
  2. Łączenie za pomocą thenApply i thenCompose
  3. Łączenie future: allOf i anyOf
  4. Obsługa błędów i asynchroniczny potok HTTP
← Powrót do Java Academy