本文向您展示如何使用新的Java 11 HttpClient API发送HTTP GET / POST请求,以及一些常用示例。
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();
本示例将GET
请求发送到https://httpbin.org/get
,并打印出响应标头,状态代码和正文。
package com.mkyong.java11.jep321;
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 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());
}
}
输出量
access-control-allow-credentials:[true]
access-control-allow-origin:[*]
connection:[keep-alive]
content-length:[273]
content-type:[application/json]
date:[Sun, 17 May 2020 08:43:18 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-5ec0f926-5ae58869cfe7162b7c3147fb"
},
"origin": "124.82.107.103",
"url": "https://httpbin.org/get"
}
2.1 HttpClient.sendAsync()
发送GET
请求异步,它将返回CompletableFuture
package com.mkyong.java11.jep321;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.time.Duration;
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> response =
httpClient.sendAsync(request, HttpResponse.BodyHandlers.ofString());
String result = response.thenApply(HttpResponse::body).get(5, TimeUnit.SECONDS);
System.out.println(result);
}
}
输出量
{
"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.1添加自定义执行程序。
private final ExecutorService executorService = Executors.newFixedThreadPool(5);
private final HttpClient httpClient = HttpClient.newBuilder()
.executor(executorService)
.build();
3.2异步发送多个并发请求。
package com.mkyong.java11.jep321;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
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;
import java.time.Duration;
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 targets = Arrays.asList(
new URI("https://httpbin.org/get?name=mkyong1"),
new URI("https://httpbin.org/get?name=mkyong2"),
new URI("https://httpbin.org/get?name=mkyong3"));
List> 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 future : result) {
System.out.println(future.get());
}
}
}
输出量
{
"args": {
"name": "mkyong1"
},
"headers": {
"Host": "httpbin.org",
"User-Agent": "Java 11 HttpClient Bot",
"X-Amzn-Trace-Id": "Root=1-5ec0fd5e-845e2a5889736f9c5bd38a38"
},
"origin": "124.82.107.103",
"url": "https://httpbin.org/get?name=mkyong1"
}
{
"args": {
"name": "mkyong2"
},
"headers": {
"Host": "httpbin.org",
"User-Agent": "Java 11 HttpClient Bot",
"X-Amzn-Trace-Id": "Root=1-5ec0fd5e-d365205a75254575c9705ca0"
},
"origin": "124.82.107.103",
"url": "https://httpbin.org/get?name=mkyong2"
}
{
"args": {
"name": "mkyong3"
},
"headers": {
"Host": "httpbin.org",
"User-Agent": "Java 11 HttpClient Bot",
"X-Amzn-Trace-Id": "Root=1-5ec0fd5e-cd61de10889128921dad6008"
},
"origin": "124.82.107.103",
"url": "https://httpbin.org/get?name=mkyong3"
}
4.1 Java 11 HttpClient
没有提供表单数据的API,我们必须手动构造它。
package com.mkyong.java11.jep321;
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
输出量
200
{
"args": {},
"data": "",
"files": {},
"form": {
"custom": "secret",
"password": "123",
"ts": "1589706608386",
"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-5ec0ff71-9f0cc3e2bc88b1c0c9c66a43"
},
"json": null,
"origin": "124.82.107.103",
"url": "https://httpbin.org/post"
}
package com.mkyong.java11.jep321;
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\":\"mkyong\",")
.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 response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
// print status code
System.out.println(response.statusCode());
// print response body
System.out.println(response.body());
}
}
输出量
200
{
"args": {},
"data": "{\"name\":\"mkyong\",\"notes\":\"hello\"}",
"files": {},
"form": {},
"headers": {
"Content-Length": "33",
"Content-Type": "application/json",
"Host": "httpbin.org",
"User-Agent": "Java 11 HttpClient Bot",
"X-Amzn-Trace-Id": "Root=1-5ec0fff9-3f6613c39c502fa5e1b79afa"
},
"json": {
"name": "mkyong",
"notes": "hello"
},
"origin": "124.82.107.103",
"url": "https://httpbin.org/post"
}
6.1启动一个简单的Spring Security WebApp,它提供HTTP基本身份验证 ,并使用新的Java 11 HttpClient
API对其进行测试
package com.mkyong.java11.jep321;
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;
// start this https://mkyong.com/spring-boot/spring-rest-spring-security-example/
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 response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
// print status code
System.out.println(response.statusCode());
// print response body
System.out.println(response.body());
}
}
7.1禁用重定向。
private final HttpClient httpClient = HttpClient.newBuilder()
.followRedirects(HttpClient.Redirect.NEVER)
.build();
阅读此HttpClient.Redirect JavaDoc
7.2超时,5秒。
private final HttpClient httpClient = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(5))
.build();
7.3设置代理
private final HttpClient httpClient = HttpClient.newBuilder()
.proxy(ProxySelector.of(new InetSocketAddress("your-company-proxy.com", 8080)))
.build();
$ git clone https://github.com/mkyong/core-java
$ cd java-11
找到jep-321
翻译自: https://mkyong.com/java/java-11-httpclient-examples/