Introduction: why do you need an HTTP client in Java?
\n\nModern Java development rarely goes without interaction with external services. Whether it's sending data to a server, retrieving information from a REST API, or integrating with cloud platforms — an HTTP client is required everywhere. In Java, there are several ways to perform an HTTP request, and it's important to choose the right approach.
\n\nFor a long time, the standard tool was the java.net.HttpURLConnection library, but with the release of Java 11, a new, more convenient module java.net.http appeared. In this article, we will cover all stages of working with an HTTP client in Java: from simple GET requests to sending JSON and error handling.
The article is aimed at developers who are already familiar with the basics of Java but want to systematize their knowledge about network requests. We will use the built-in HttpClient from Java 11+, as this is the modern and recommended approach.
1. HTTP client basics: creation and configuration
\n\nBefore sending requests, you need to create an instance of HttpClient. This is the central object through which all HTTP operations are performed. Let's look at the basic configuration.
Creating a client
\n\nThe simplest way is to use the static method newHttpClient():
import java.net.http.HttpClient;\n\nHttpClient client = HttpClient.newHttpClient();\n\nHowever, for real projects, configuration of timeouts, protocol version, or proxy is often required. Here is an example of advanced configuration:
\n\nimport java.net.http.HttpClient;\nimport java.time.Duration;\n\nHttpClient client = HttpClient.newBuilder()\n .version(HttpClient.Version.HTTP_2) // use HTTP/2\n .connectTimeout(Duration.ofSeconds(10)) // connection timeout\n .followRedirects(HttpClient.Redirect.NORMAL) // automatic redirect following\n .build();\n\nImportant configuration parameters
\n\n- \n
- version — choice between HTTP/1.1 and HTTP/2 (default is HTTP/2 if the server supports it) \n
- connectTimeout — maximum connection waiting time \n
- followRedirects — redirect handling policy (NEVER, ALWAYS, NORMAL) \n
- proxy — proxy server configuration (if required) \n
Note: one instance of HttpClient can be used for many requests. It is thread-safe, so you can create it once and reuse it throughout the application.
2. Creating and sending HTTP requests
\n\nNow let's move on to the main part — forming requests. In Java 11+, the HttpRequest class is used for this. Let's look at the main types of requests.
GET request: retrieving data
\n\nGET is the simplest type of request. It is used to retrieve data from the server. Example:
\n\nimport java.net.URI;\nimport java.net.http.HttpRequest;\nimport java.net.http.HttpResponse;\n\nHttpRequest request = HttpRequest.newBuilder()\n .uri(URI.create("https://api.example.com/users"))\n .GET() // explicitly specify the method (can be omitted, GET is default)\n .build();\n\nHttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());\n\nSystem.out.println("Status: " + response.statusCode());\nSystem.out.println("Response body: " + response.body());\n\nThe send() method performs a synchronous request. If asynchronous execution is needed, use sendAsync(), which returns a CompletableFuture.
POST request: sending data
\n\nPOST is used to send data to the server. Most often this is JSON or form data. Let's look at both options.
\n\nPOST with JSON:
\n\nimport java.net.http.HttpRequest.BodyPublishers;\n\nString json = "{\\"name\\":\\"Ivan\\",\\"email\\":\\"iva