HTTP client in Java: making requests correctly
In modern web development, almost no application can function without interacting with remote servers. Whether it's integration with REST API, data loading, or form submission — the ability to work correctly with HTTP requests in Java is a mandatory skill for a developer. In this article, we will analyze how to create a reliable HTTP client in Java, consider modern approaches and best practices.
Why is it important to use the right HTTP client?
Many novice developers use the outdated HttpURLConnection class, which appeared back in Java 1.1. Although it works, its API is cumbersome, inconvenient, and requires a lot of boilerplate code. Starting with Java 11, the standard library introduced the modern java.net.http.HttpClient, which offers:
- Support for HTTP/2 and WebSocket
- Asynchronous requests via CompletableFuture
- Simple and clear Builder pattern
- Automatic handling of cookies and redirects
Basics of working with HttpClient in Java 11+
Let's consider a basic example of sending a GET request. First, we create a client instance, then form the request and send it.
import java.net.URI;import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;import java.time.Duration;
public class SimpleHttpClient { public static void main(String[] args) throws Exception { // Create a client with connection timeout HttpClient client = HttpClient.newBuilder() .connectTimeout(Duration.ofSeconds(10)) .build();
// Form a GET request HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://api.example.com/data")) .timeout(Duration.ofSeconds(30)) .header("Accept", "application/json") .GET() .build();
// Send the request and receive the response HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println("Status: " + response.statusCode()); System.out.println("Response body: " + response.body()); }}Note the use of BodyHandlers.ofString() — this is a convenient way to get the response body as a string. If you need to process JSON, it's better to use BodyHandlers.ofInputStream() and pass it to the parser.
Sending a POST request with a body
To send data to the server (for example, when registering a user), a POST request is used. Let's consider an example with sending JSON:
import java.net.URI;import java.net.http.HttpClient;import java.net.http.HttpRequest;import java.net.http.HttpResponse;import java.time.Duration;
public class PostRequestExample { public static void main(String[] args) throws Exception { HttpClient client = HttpClient.newHttpClient();
String json = """ { "name": "Ivan Ivanov", "email": "ivan@example.com", "age": 30 } """;
HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://api.example.com/users")) .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(json)) .timeout(Duration.ofSeconds(15)) .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 201) { System.out.println("User created successfully!"); System.out.println("ID: " + response.body()); } else { System