This article shows you how to use the new Java 11 HttpClient APIs to send HTTP GET/POST requests, and some frequent used examples.
HttpClient httpClient = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2)
.followRedirects(HttpClient.Redirect.NORMAL)
.connectTimeout(Duration.ofSeconds(20))
.proxy(ProxySelector.of(new InetSocketAddress("proxy.yourcompany.com", 80)))
.authenticator(Authenticator.getDefault())
.build();
1. Synchronous Example
This example sends a GET request to https://httpbin.org/get, and print out the response header, status code, and body.
HttpClientSynchronous.java
package com.favtuts.http;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpHeaders;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class HttpClientSynchronous {
private static final HttpClient httpClient = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_1_1)
.connectTimeout(Duration.ofSeconds(10))
.build();
public static void main(String[] args) throws IOException, InterruptedException {
HttpRequest request = HttpRequest.newBuilder()
.GET()
.uri(URI.create("https://httpbin.org/get"))
.setHeader("User-Agent", "Java 11 HttpClient Bot") // add request header
.build();
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
// print response headers
HttpHeaders headers = response.headers();
headers.map().forEach((k, v) -> System.out.println(k + ":" + v));
// print status code
System.out.println(response.statusCode());
// print response body
System.out.println(response.body());
}
}
Output
access-control-allow-credentials:[true]
access-control-allow-origin:[*]
connection:[keep-alive]
content-length:[271]
content-type:[application/json]
date:[Tue, 10 May 2022 09:46:13 GMT]
server:[gunicorn/19.9.0]
200
{
"args": {},
"headers": {
"Content-Length": "0",
"Host": "httpbin.org",
"User-Agent": "Java 11 HttpClient Bot",
"X-Amzn-Trace-Id": "Root=1-627a3465-59aa4d452eda31397a009a77"
},
"origin": "14.162.33.98",
"url": "https://httpbin.org/get"
}
2. Asynchronous Example
2.1 HttpClient.sendAsync() to send a GET request asynchronous, it will return a CompletableFuture
HttpClientAsynchronous.java
package com.favtuts.http;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
public class HttpClientAsynchronous {
private static final HttpClient httpClient = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2)
.connectTimeout(Duration.ofSeconds(10))
.build();
public static void main(String[] args) throws Exception {
HttpRequest request = HttpRequest.newBuilder()
.GET()
.uri(URI.create("https://httpbin.org/get"))
.setHeader("User-Agent", "Java 11 HttpClient Bot")
.build();
CompletableFuture<HttpResponse<String>> response =
httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString());
String result = response.thenApply(HttpResponse::body).get(5, TimeUnit.SECONDS);
System.out.println(result);
}
}
Output
{
"args": {},
"headers": {
"Host": "httpbin.org",
"User-Agent": "Java 11 HttpClient Bot",
"X-Amzn-Trace-Id": "Root=1-5ec0fb51-2c5dcf98167c6418bd555548"
},
"origin": "124.82.107.103",
"url": "https://httpbin.org/get"
}
3. Custom Executor + Concurrent Requests
3.1 Add a custom executor.
private final ExecutorService executorService = Executors.newFixedThreadPool(5);
private final HttpClient httpClient = HttpClient.newBuilder()
.executor(executorService)
.build();
3.2 Send multiple concurrent requests asynchronously.
HttpClientCustomExecutor.java
package com.favtuts.http;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
public class HttpClientCustomExecutor {
// custom executor
private static final ExecutorService executorService = Executors.newFixedThreadPool(5);
private static final HttpClient httpClient = HttpClient.newBuilder()
.executor(executorService)
.version(HttpClient.Version.HTTP_2)
.connectTimeout(Duration.ofSeconds(10))
.build();
public static void main(String[] args) throws Exception {
List<URI> targets = Arrays.asList(
new URI("https://httpbin.org/get?name=favtuts1"),
new URI("https://httpbin.org/get?name=favtuts2"),
new URI("https://httpbin.org/get?name=favtuts3")
);
List<CompletableFuture<String>> result = targets.stream()
.map(url -> httpClient.sendAsync(
HttpRequest.newBuilder(url)
.GET()
.setHeader("User-Agent", "Java 11 HttpClient Bot")
.build()
,
HttpResponse.BodyHandlers.ofString())
.thenApply(response -> response.body())
)
.collect(Collectors.toList());
for (CompletableFuture<String> future : result) {
System.out.println(future.get());
}
}
}
Output
{
"args": {
"name": "favtuts1"
},
"headers": {
"Host": "httpbin.org",
"User-Agent": "Java 11 HttpClient Bot",
"X-Amzn-Trace-Id": "Root=1-627a753c-14ae27021dbdabc23f2f6c4a"
},
"origin": "14.162.33.98",
"url": "https://httpbin.org/get?name=favtuts1"
}
{
"args": {
"name": "favtuts2"
},
"headers": {
"Host": "httpbin.org",
"User-Agent": "Java 11 HttpClient Bot",
"X-Amzn-Trace-Id": "Root=1-627a753c-2ce53d22544b7da802f368d0"
},
"origin": "14.162.33.98",
"url": "https://httpbin.org/get?name=favtuts2"
}
{
"args": {
"name": "favtuts3"
},
"headers": {
"Host": "httpbin.org",
"User-Agent": "Java 11 HttpClient Bot",
"X-Amzn-Trace-Id": "Root=1-627a753c-4d63aa946ec2103234231fb7"
},
"origin": "14.162.33.98",
"url": "https://httpbin.org/get?name=favtuts3"
}
4. POST Form Parameters
4.1 Java 11 HttpClient didn’t provide API for the form data, we have to construct it manually.
HttpClientPostForm.java
package com.favtuts.http;
import java.io.IOException;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
public class HttpClientPostForm {
private static final HttpClient httpClient = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2)
.connectTimeout(Duration.ofSeconds(10))
.build();
public static void main(String[] args) throws IOException, InterruptedException {
// form parameters
Map<Object, Object> data = new HashMap<>();
data.put("username", "abc");
data.put("password", "123");
data.put("custom", "secret");
data.put("ts", System.currentTimeMillis());
HttpRequest request = HttpRequest.newBuilder()
.POST(ofFormData(data))
.uri(URI.create("https://httpbin.org/post"))
.setHeader("User-Agent", "Java 11 HttpClient Bot") // add request header
.header("Content-Type", "application/x-www-form-urlencoded")
.build();
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
// print status code
System.out.println(response.statusCode());
// print response body
System.out.println(response.body());
}
// Sample: 'password=123&custom=secret&username=abc&ts=1570704369823'
public static HttpRequest.BodyPublisher ofFormData(Map<Object, Object> data) {
var builder = new StringBuilder();
for (Map.Entry<Object, Object> entry : data.entrySet()) {
if (builder.length() > 0) {
builder.append("&");
}
builder.append(URLEncoder.encode(entry.getKey().toString(), StandardCharsets.UTF_8));
builder.append("=");
builder.append(URLEncoder.encode(entry.getValue().toString(), StandardCharsets.UTF_8));
}
return HttpRequest.BodyPublishers.ofString(builder.toString());
}
}
Output
200
{
"args": {},
"data": "",
"files": {},
"form": {
"custom": "secret",
"password": "123",
"ts": "1652193037757",
"username": "abc"
},
"headers": {
"Content-Length": "56",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "Java 11 HttpClient Bot",
"X-Amzn-Trace-Id": "Root=1-627a770f-6fbdfa77156ce12779ae2ae0"
},
"json": null,
"origin": "14.162.33.98",
"url": "https://httpbin.org/post"
}
5. POST JSON
HttpClientPostJSON.java
package com.favtuts.http;
import java.io.IOException;
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 HttpClientPostJSON {
private static final HttpClient httpClient = HttpClient.newBuilder()
.version(HttpClient.Version.HTTP_2)
.connectTimeout(Duration.ofSeconds(10))
.build();
public static void main(String[] args) throws IOException, InterruptedException {
// json formatted data
String json = new StringBuilder()
.append("{")
.append("\"name\":\"favtuts\",")
.append("\"notes\":\"hello\"")
.append("}").toString();
// add json header
HttpRequest request = HttpRequest.newBuilder()
.POST(HttpRequest.BodyPublishers.ofString(json))
.uri(URI.create("https://httpbin.org/post"))
.setHeader("User-Agent", "Java 11 HttpClient Bot") // add request header
.header("Content-Type", "application/json")
.build();
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
// print status code
System.out.println(response.statusCode());
// print response body
System.out.println(response.body());
}
}
Output
200
{
"args": {},
"data": "{\"name\":\"favtuts\",\"notes\":\"hello\"}",
"files": {},
"form": {},
"headers": {
"Content-Length": "34",
"Content-Type": "application/json",
"Host": "httpbin.org",
"User-Agent": "Java 11 HttpClient Bot",
"X-Amzn-Trace-Id": "Root=1-627a784a-0b2535867b89813140fca0c7"
},
"json": {
"name": "favtuts",
"notes": "hello"
},
"origin": "14.162.33.98",
"url": "https://httpbin.org/post"
}
6. Authentication
6.1 Start a simple Spring Security WebApp provides HTTP basic authentication, and test it with the new Java 11 HttpClient APIs
HttpClientAuthentication.java
package com.favtuts.http;
import java.io.IOException;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
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 HttpClientAuthentication {
private static final HttpClient httpClient = HttpClient.newBuilder()
.authenticator(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(
"user",
"password".toCharArray());
}
})
.connectTimeout(Duration.ofSeconds(10))
.build();
public static void main(String[] args) throws IOException, InterruptedException {
HttpRequest request = HttpRequest.newBuilder()
.GET()
.uri(URI.create("http://localhost:8080/books"))
.setHeader("User-Agent", "Java 11 HttpClient Bot") // add request header
.build();
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
// print status code
System.out.println(response.statusCode());
// print response body
System.out.println(response.body());
}
}
7. FAQs
7.1 Disabled Redirect.
private final HttpClient httpClient = HttpClient.newBuilder()
.followRedirects(HttpClient.Redirect.NEVER)
.build();
Read this HttpClient.Redirect JavaDoc
7.2 Timeout, 5 seconds.
private final HttpClient httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(5))
.build();
7.3 Set a Proxy.
private final HttpClient httpClient = HttpClient.newBuilder()
.proxy(ProxySelector.of(new InetSocketAddress("your-company-proxy.com", 8080)))
.build();
Download Source Code
$ git clone https://github.com/favtuts/java-core-tutorials-examples
$ cd java-misc/http