I/O, Serialization & Networking
The HTTP Client
java.net.http.HttpClient (Java 11) is the modern built-in: fluent requests, HTTP/2, synchronous or CompletableFuture async, and pluggable body handlers. No third-party dependency needed for straightforward HTTP.- Build one
HttpClient, reuse it — it pools connections send(request, bodyHandler)blocks;sendAsyncreturnsCompletableFuture<HttpResponse<T>>- Body handlers:
ofString,ofFile,ofInputStream,ofLines; publishers for upload - HTTP/2 by default with HTTP/1.1 fallback; redirects and timeouts are opt-in configuration
- Check
response.statusCode()— non-2xx does not throw
HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(5))
.followRedirects(HttpClient.Redirect.NORMAL)
.build();
HttpRequest get = HttpRequest.newBuilder(URI.create("https://api.example.com/users"))
.header("Accept", "application/json")
.timeout(Duration.ofSeconds(10))
.GET().build();
HttpResponse<String> resp = client.send(get, HttpResponse.BodyHandlers.ofString());
if (resp.statusCode() == 200) process(resp.body());
HttpRequest post = HttpRequest.newBuilder(URI.create("https://api.example.com/users"))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(json))
.build();List<CompletableFuture<String>> futures = urls.stream()
.map(u -> client.sendAsync(reqFor(u), BodyHandlers.ofString())
.thenApply(HttpResponse::body))
.toList();
CompletableFuture.allOf(futures.toArray(CompletableFuture[]::new)).join();The async form rides on Completable Future — compose, time out (orTimeout), and fan out without blocking threads. With Virtual Threads, the synchronous API inside cheap threads is often the most readable concurrent design: straight-line code, per-request thread, no callback chains.