Java 11 introduced the HTTP Client which can be used to send requests over the network and retrieves their responses. HTTP Client replaces the HttpUrlConnection class as it is considered old and doesn’t support ease of use. HTTP Client API supports both HTTP/1.1 and HTTP/2.
HttpClient is also immutable, meaning it can be used to send multiple requests.
Each HttpRequest must be supplied with a BodyHandler and its (BodyHandler) function is to determine how to handle the response if there is any.
Requests can be either sent synchronously or asynchronously
- send(HttpRequest, BodyHandler) blocks until the request has been sent and the response has been received
- sendAsync(HttpRequest, BodyHandler) sends the request and at the same time receives the response (asynchronously). This method returns CompletableFuture which is completed only when the response becomes available.
HttpResponse.BodyHandler
- allows inspection of the response code before the actual response body has been received
HttpResponse.BodyHandlers
BodyHandlers exist for the sole purpose of handling response body types. Some examples:
- BodyHandlers.ofByteArray()
- BodyHandlers.ofString()
- BodyHandlers.ofFile()
- BodyHandlers.ofInputStream()
- etc.
Data as reactive-streams
- The HttpClient is effectively a Subscriber of request body and a Publisher of response body bytes
- The request and response bodies are exposed as reactive streams (streams of data with non-blocking back pressure)
HttpRequest.BodyPublisher
- Converts Java objects into byte buffers suitable for sending as a request body
HttpRequest.BodyPublishers
- BodyPublishers::ofByteArray(byte[])
- BodyPublishers::ofFIle(Path)
- BodyPublishers::ofString(String)
- etc.
HttpRequest.BodySubscriber
- consumes response body bytes and converts them into a Java type
With that out of the way, let’s see some implementation. First, we will send a GET request:
HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://javatutorial.net/")) .build();
Now, let’s send an HTTP Request. I will show you both the synchronous and asynchronous examples:
Synchronous (blocks until HttpResponse is available) GET
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpClient.newBuilder() .uri(URI.create("https://javatutorial.net/") .version(Version.HTTP_1_1) .connectTimeout(Duration.ofSeconds(20)) .authenticator(Authenticator.getDefault()) .build(); HttpResponse<String> response = client.send(request, BodyHandlers.ofString()); System.out.println(response.statusCode()); System.out.println(response.body());
Asynchronous GET
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://javatutorial.net/")) .connectTimeout(Duration.ofSeconds(20)) .build(); client.sendAsync(request, BodyHandlers.ofString()) .thenApply(HttpResponse::body) .thenAccept(System.out::println);
POST
HttpClient client = HttpClient.newBuilder().build(); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://javatutorial.net/")) .POST(BodyPublishers.ofString(data)) .build(); HttpResponse<?> response = client.send(request, discarding());
Summary
The HTTP Client’s role is to replace the URLConnection API and is standardized in Java 11 as part of the Java SE Platform and is located in the java.net.http package. One key advantage is that it uses modern Java language as well as API features.