HttpClient 5 使用详细教程,代码示例 - 快速上手
依赖
【Maven依赖】
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents.client5/httpclient5 -->
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.1.3</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.httpcomponents.client5/httpclient5-fluent -->
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5-fluent</artifactId>
<version>5.1.3</version>
</dependency>
示例
GET请求
【代码】
01
说明
- 类名;
HttpClient5Get.java
02
import java.io.IOException;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
public class HttpClient5Get {
public static void main(String[] args) {
String result = get("http://httpbin.org/get");
System.out.println(result);
}
public static String get(String url) {
String resultContent = null;
HttpGet httpGet = new HttpGet(url);
try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
try (CloseableHttpResponse response = httpclient.execute(httpGet)) {
// 获取状态码
System.out.println(response.getVersion()); // HTTP/1.1
System.out.println(response.getCode()); // 200
System.out.println(response.getReasonPhrase()); // OK
HttpEntity entity = response.getEntity();
// 获取响应信息
resultContent = EntityUtils.toString(entity);
}
} catch (IOException | ParseException e) {
e.printStackTrace();
}
return resultContent;
}
}
【结果】
01
Fluent GET
【说明】
- 使用"Apache HttpClient 5"提供的"Fluent API"可以更便捷的发起"GET"请求,但是可操作的地方较少;
- 只需要"
<artifactId>httpclient5-fluent</artifactId>
"依赖即可运行;
【代码】
01
说明
- 类名;
HttpClient5GetFluent.java
02
import java.io.IOException;
import org.apache.hc.client5.http.fluent.Request;
import org.apache.hc.client5.http.fluent.Response;
public class HttpClient5GetFluent {
public static void main(String[] args) {
System.out.println(get("http://httpbin.org/get"));
}
public static String get(String url) {
String result = null;
try {
Response response = Request.get(url).execute();
result = response.returnContent().asString();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
}
【结果】
GET 请求参数
【说明】
- 使用
URIBuilder
的addParameters()
方法来构建"GET"请求的参数;
【代码】
01
说明
- 类名;
HttpClient5GetParams.java
02
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.NameValuePair;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.message.BasicNameValuePair;
import org.apache.hc.core5.net.URIBuilder;
public class HttpClient5GetParams {
public static void main(String[] args) {
String result = get("http://httpbin.org/get");
System.out.println(result);
}
public static String get(String url) {
String resultContent = null;
HttpGet httpGet = new HttpGet(url);
// 表单参数
List<NameValuePair> nvps = new ArrayList<>();
// GET 请求参数
nvps.add(new BasicNameValuePair("username", "SUNxRUN"));
nvps.add(new BasicNameValuePair("password", "12345678"));
// 增加到请求 URL 中
try {
URI uri = new URIBuilder(new URI(url))
.addParameters(nvps)
.build();
httpGet.setUri(uri);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
try (CloseableHttpResponse response = httpclient.execute(httpGet)) {
// 获取状态码
System.out.println(response.getVersion()); // HTTP/1.1
System.out.println(response.getCode()); // 200
System.out.println(response.getReasonPhrase()); // OK
HttpEntity entity = response.getEntity();
// 获取响应信息
resultContent = EntityUtils.toString(entity);
}
} catch (IOException | ParseException e) {
e.printStackTrace();
}
return resultContent;
}
}
【结果】
POST 请求
【说明】
- 参数:“
username=SUNxRUN&password=12345678
”;
【代码】
01
说明
- 类名;
HttpClient5Post.java
02
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.NameValuePair;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.message.BasicNameValuePair;
public class HttpClient5Post {
public static void main(String[] args) {
String result = post("http://httpbin.org/post");
System.out.println(result);
}
public static String post(String url) {
String result = null;
HttpPost httpPost = new HttpPost(url);
// 表单参数
List<NameValuePair> nvps = new ArrayList<>();
// POST 请求参数
nvps.add(new BasicNameValuePair("username", "SUNxRUN"));
nvps.add(new BasicNameValuePair("password", "12345678"));
httpPost.setEntity(new UrlEncodedFormEntity(nvps));
try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
try (CloseableHttpResponse response = httpclient.execute(httpPost)) {
System.out.println(response.getVersion()); // HTTP/1.1
System.out.println(response.getCode()); // 200
System.out.println(response.getReasonPhrase()); // OK
HttpEntity entity = response.getEntity();
// 获取响应信息
result = EntityUtils.toString(entity);
// 确保流被完全消费
EntityUtils.consume(entity);
}
} catch (IOException | ParseException e) {
e.printStackTrace();
}
return result;
}
}
【结果】
Fluent POST
【说明】
- 使用"Apache HttpClient 5"提供的"Fluent API"可以更便捷的发起"POST"请求,但是可操作的地方较少;
- 参数:“
username=SUNxRUN&password=12345678
”;
【代码】
01
说明
- 类名;
HttpClient5PostFluent.java
02
import java.io.IOException;
import org.apache.hc.client5.http.fluent.Request;
import org.apache.hc.core5.http.message.BasicNameValuePair;
public class HttpClient5PostFluent {
public static void main(String[] args) {
String result = post("http://httpbin.org/post");
System.out.println(result);
}
public static String post(String url) {
String result = null;
Request request = Request.post(url);
// POST 请求参数
request.bodyForm(
new BasicNameValuePair("username", "SUNxRun"),
new BasicNameValuePair("password", "12345678"));
try {
result = request.execute().returnContent().asString();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
}
【结果】
POST JSON 参数
【说明】
- 使用
StringEntity
类存入 JSON 参数;
【代码】
01
说明
- 类名;
HttpClient5PostWithJson.java
02
import java.io.IOException;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;
public class HttpClient5PostWithJson {
public static void main(String[] args) {
String json = "{"
+ " \"password\": \"121345678\","
+ " \"username\": \"SUNxRUN\""
+ "}";
String result = post("http://httpbin.org/post", json);
System.out.println(result);
}
public static String post(String url, String jsonBody) {
String result = null;
HttpPost httpPost = new HttpPost(url);
httpPost.setEntity(new StringEntity(jsonBody, ContentType.APPLICATION_JSON));
try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
try (CloseableHttpResponse response = httpclient.execute(httpPost)) {
// 获取响应信息
result = EntityUtils.toString(response.getEntity());
}
} catch (IOException | ParseException e) {
e.printStackTrace();
}
return result;
}
}
【结果】
设置超时
【说明】
- 使用
RequestConfig
对象来配置超时时间;
【代码】
01
说明
- 类名;
HttpClient5GetWithTimeout.java
02
import java.io.IOException;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.util.Timeout;
public class HttpClient5GetWithTimeout {
public static void main(String[] args) {
String result = get("http://httpbin.org/get");
System.out.println(result);
}
public static String get(String url) {
String resultContent = null;
// 设置超时时间
RequestConfig config = RequestConfig.custom()
.setConnectTimeout(Timeout.ofMilliseconds(5000L))
.setConnectionRequestTimeout(Timeout.ofMilliseconds(5000L))
.setResponseTimeout(Timeout.ofMilliseconds(5000L))
.build();
// 请求级别的超时
HttpGet httpGet = new HttpGet(url);
//httpGet.setConfig(config);
//try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
// 客户端级别的超时
try (CloseableHttpClient httpclient = HttpClients.custom().setDefaultRequestConfig(config).build()) {
try (CloseableHttpResponse response = httpclient.execute(httpGet)) {
// 获取状态码
System.out.println(response.getVersion()); // HTTP/1.1
System.out.println(response.getCode()); // 200
System.out.println(response.getReasonPhrase()); // OK
HttpEntity entity = response.getEntity();
// 获取响应信息
resultContent = EntityUtils.toString(entity);
}
} catch (IOException | ParseException e) {
e.printStackTrace();
}
return resultContent;
}
}
异步请求
【代码】
01
说明
- 类名;
HttpClient5Async.java
02
【说明】
- 下面演示三种"HttpClient 5"异步请求方式;
import java.io.IOException;
import java.nio.CharBuffer;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import org.apache.hc.client5.http.async.methods.AbstractCharResponseConsumer;
import org.apache.hc.client5.http.async.methods.SimpleHttpRequest;
import org.apache.hc.client5.http.async.methods.SimpleHttpRequests;
import org.apache.hc.client5.http.async.methods.SimpleHttpResponse;
import org.apache.hc.client5.http.impl.async.CloseableHttpAsyncClient;
import org.apache.hc.client5.http.impl.async.HttpAsyncClients;
import org.apache.hc.core5.concurrent.FutureCallback;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.HttpException;
import org.apache.hc.core5.http.HttpResponse;
import org.apache.hc.core5.http.nio.AsyncRequestProducer;
import org.apache.hc.core5.http.nio.support.AsyncRequestBuilder;
public class HttpClient5Async {
public static void main(String[] args) {
getAsync1("http://httpbin.org/get");
getAsync2("http://httpbin.org/get");
getAsync3("http://httpbin.org/get");
}
/**
* 异步请求
*
* @param url
* @return
*/
public static String getAsync1(String url) {
try (CloseableHttpAsyncClient httpclient = HttpAsyncClients.createDefault()) {
// 开始 http client
httpclient.start();
// 执行请求
SimpleHttpRequest request1 = SimpleHttpRequests.get(url);
Future<SimpleHttpResponse> future = httpclient.execute(request1, null);
// 等待直到返回完毕
SimpleHttpResponse response1 = future.get();
System.out.println("getAsync1:" + request1.getRequestUri() + "->" + response1.getCode());
} catch (IOException | ExecutionException | InterruptedException e) {
throw new RuntimeException(e);
}
return null;
}
/**
* 异步请求,根据响应情况回调
*
* @param url
* @return
*/
public static String getAsync2(String url) {
try (CloseableHttpAsyncClient httpclient = HttpAsyncClients.createDefault()) {
// 开始 http client
httpclient.start();
// 根据请求响应情况进行回调操作
CountDownLatch latch = new CountDownLatch(1);
SimpleHttpRequest request = SimpleHttpRequests.get(url);
httpclient.execute(request, new FutureCallback<SimpleHttpResponse>() {
@Override
public void completed(SimpleHttpResponse response2) {
latch.countDown();
System.out.println("getAsync2:" + request.getRequestUri() + "->" + response2.getCode());
}
@Override
public void failed(Exception ex) {
latch.countDown();
System.out.println("getAsync2:" + request.getRequestUri() + "->" + ex);
}
@Override
public void cancelled() {
latch.countDown();
System.out.println("getAsync2:" + request.getRequestUri() + " cancelled");
}
});
latch.await();
} catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
}
return null;
}
/**
* 异步请求,对响应流做点什么
*
* @param url
* @return
*/
public static String getAsync3(String url) {
try (CloseableHttpAsyncClient httpclient = HttpAsyncClients.createDefault()) {
// 开始 http client
httpclient.start();
// 根据请求响应情况进行回调操作
SimpleHttpRequest request = SimpleHttpRequests.get(url);
CountDownLatch latch = new CountDownLatch(1);
AsyncRequestProducer producer = AsyncRequestBuilder.get("http://httpbin.org/get").build();
AbstractCharResponseConsumer<HttpResponse> consumer3 = new AbstractCharResponseConsumer<HttpResponse>() {
HttpResponse response;
@Override
protected void start(HttpResponse response, ContentType contentType) throws HttpException, IOException {
System.out.println("getAsync3: 开始响应....");
this.response = response;
}
@Override
protected int capacityIncrement() {
return Integer.MAX_VALUE;
}
@Override
protected void data(CharBuffer data, boolean endOfStream) throws IOException {
System.out.println("getAsync3: 收到数据....");
// Do something useful
}
@Override
protected HttpResponse buildResult() throws IOException {
System.out.println("getAsync3: 接收完毕...");
return response;
}
@Override
public void releaseResources() {
}
};
httpclient.execute(producer, consumer3, new FutureCallback<HttpResponse>() {
@Override
public void completed(HttpResponse response) {
latch.countDown();
System.out.println("getAsync3: " + request.getRequestUri() + "->" + response.getCode());
}
@Override
public void failed(Exception ex) {
latch.countDown();
System.out.println("getAsync3: " + request.getRequestUri() + "->" + ex);
}
@Override
public void cancelled() {
latch.countDown();
System.out.println("getAsync3: " + request.getRequestUri() + " cancelled");
}
});
latch.await();
} catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
}
return null;
}
}
【结果】
获取 Cookie
读取文件内容请求
表单登录
Basic Authorization
Digest Authorization
拦截器
【说明】
- "HttpClient 5"中的拦截器可以对请求过程的各个阶段进行拦截处理;
- 通过
HttpClientBuilder
中的关于Interceptor
的方法可以看到可以进行拦截的节点;
【代码】
01
说明
- 类名;
HttpClient5Interceptors.java
02
说明
- 下面编写一个示例,发起三次请求,每次请求都在请求头"herader"中增加一个
request-id
参数,然后对request-id
值为 2 的请求直接响应"404"结束;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.hc.client5.http.classic.ExecChain;
import org.apache.hc.client5.http.classic.ExecChain.Scope;
import org.apache.hc.client5.http.classic.ExecChainHandler;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.ChainElement;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.ClassicHttpRequest;
import org.apache.hc.core5.http.ClassicHttpResponse;
import org.apache.hc.core5.http.ContentType;
import org.apache.hc.core5.http.EntityDetails;
import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpException;
import org.apache.hc.core5.http.HttpRequest;
import org.apache.hc.core5.http.HttpRequestInterceptor;
import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.message.BasicClassicHttpResponse;
import org.apache.hc.core5.http.protocol.HttpContext;
/**
* 展示如何在请求和响应时进行拦截进行自定义处理。
*/
public class HttpClient5Interceptors {
public static void main(final String[] args) throws Exception {
try (final CloseableHttpClient httpclient = HttpClients.custom()
// 添加一个请求 id 到请求 header
.addRequestInterceptorFirst(new HttpRequestInterceptor() {
private final AtomicLong count = new AtomicLong(0);
@Override
public void process(
final HttpRequest request,
final EntityDetails entity,
final HttpContext context) throws HttpException, IOException {
request.setHeader("request-id", Long.toString(count.incrementAndGet()));
}
})
.addExecInterceptorAfter(ChainElement.PROTOCOL.name(), "custom", new ExecChainHandler() {
// 请求 id 为 2 的,模拟 404 响应,并自定义响应的内容。
@Override
public ClassicHttpResponse execute(
final ClassicHttpRequest request,
final Scope scope,
final ExecChain chain) throws IOException, HttpException {
final Header idHeader = request.getFirstHeader("request-id");
if (idHeader != null && "2".equalsIgnoreCase(idHeader.getValue())) {
final ClassicHttpResponse response = new BasicClassicHttpResponse(HttpStatus.SC_NOT_FOUND,
"Oppsie");
response.setEntity(new StringEntity("bad luck", ContentType.TEXT_PLAIN));
return response;
} else {
return chain.proceed(request, scope);
}
}
})
.build()) {
for (int i = 0; i < 3; i++) {
final HttpGet httpget = new HttpGet("http://httpbin.org/get");
try (final CloseableHttpResponse response = httpclient.execute(httpget)) {
System.out.println("----------------------------------------");
System.out.println("执行请求 " + httpget.getMethod() + " " + httpget.getUri());
System.out.println(response.getCode() + " " + response.getReasonPhrase());
System.out.println(EntityUtils.toString(response.getEntity()));
}
}
}
}
}
【结果】
未完待续…