4.5日学习打卡
Apache Commons HttpClient
简介
Apache HttpClient 组件是为扩展而设计的,同时提供对基本HTTP协议的强大支持。
http://java.net包提供了通过HTTP访问资源的基本功能,但它并没有提供许多应用程序所需的全部灵活性或功能。HttpClient 组件通过提供一个高效、最新、功能丰富的包来填补这一空白,该包实现了最新HTTP标准的客户端。
HttpClient 过去是 Commons 的一部分,现在是 Apache HttpComponents 的一部分。Apache HttpComponents 是 Apache 的顶级项目,负责创建和维护专注于 HTTP 和相关协议的 Java 组件工具集。因此文章后面将不再使用 Commons HttpClient 字样,而是使用 HttpClient 。
HttpClient 目前有三个大版本,他们是不兼容的,可以同时存在。HttpClient 3过去是 Commons 的一部分,所以一般来说看到 Apache HttpClient 3的说法指的就是 Commons HttpClient,所属包 org.apache.commons.httpclient,maven 依赖如下
<!-- HttpClient 3 -->
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
HttpClient 4 指的是 Apache HttpComponents 下的项目,所属包 org.apache.http,maven 依赖如下
<!-- HttpClient 4 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
HttpClient 5 指的是 Apache HttpComponents 下的最新项目,包结构是 org.apache.hc,依赖如下
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.1</version>
</dependency>
HttpClient 3 早已不在维护,推荐使用最新的HttpClient 5。HttpClient 5 支持(经典API)(异步API)(反应式API)。
下面我将简单介绍下这几个版本 HttpClient 的用法。
-
原生API
我们先来看看如果不使用 HttpClient 而是使用 Java 原生 API,写一个 http 请求的例子
package com.jjy.httpclient5demo.test;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
public class JavaApi {
public static void main(String[] args) {
HttpsURLConnection conn = null;
try {
URL url = new URL("https://httpbin.org/get");
conn = (HttpsURLConnection) url.openConnection();
// https请求需要设置证书,为了简单此处默认信任服务器不做证书校验
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[]{new X509TrustManager() {
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
}}, new java.security.SecureRandom());
conn.setSSLSocketFactory(sc.getSocketFactory());
conn.setHostnameVerifier((s, sslSession) -> true);
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
conn.setUseCaches(false);
conn.connect();
InputStream is = conn.getInputStream();
try (BufferedReader br = new BufferedReader(
new InputStreamReader(is))) {
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
sb.deleteCharAt(sb.length() - 1);
System.out.println(sb.toString());
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (conn != null) {
conn.disconnect();
}
}
}
}
package com.jjy.httpclient5demo.test;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpHeaders;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
public class NativeJavaHttpClient {
public static String get(String url) {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Accept", "application/json") // 如果需要的话,设置请求头
.GET()
.build();
try {
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
int statusCode = response.statusCode();
System.out.println("Status Code: " + statusCode);
System.out.println("Response Headers: " + response.headers());
return response.body();
} catch (IOException | InterruptedException e) {
e.printStackTrace();
return null;
}
}
public static void main(String[] args) {
String url = "http://httpbin.org/get";
String responseContent = NativeJavaHttpClient.get(url);
System.out.println(responseContent);
}
}
我们看到这个例子是一个相对比较简单的 https 的 get请求,没有参数。代码已经比较复杂了,如果是 post 请求,需要传递参数,需要保存cookie(有些请求需求登录,我们还要先模拟登录请求后手动将 cookie 保存下来,下次请求在把 cookie 设置上)等场景代码将更为复杂。并且原生 API 默认不支持异步不支持响应式等,这时候就轮到 HttpClient 大显手身了。
- HttpClient 3
package com.jjy.httpclient5demo.test;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import java.io.IOException;
public class HttpClient3 {
public static void main(String[] args) {
// httpClient对象是线程安全的,可以单例使用,提升性能
HttpClient httpClient = new HttpClient();
// 设置连接超时 和 socket超时
httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(2000);
httpClient.getHttpConnectionManager().getParams().setSoTimeout(5000); // 响应超时
HttpMethod getM = new GetMethod("http://httpbin.org/get");
// 设置请求头
getM.setRequestHeader("Content-Type", "application/json");
NameValuePair p1 = new NameValuePair("name", "zs");
NameValuePair p2 = new NameValuePair("age", "11");
// 设置查询参数,相当于 ?name=zs&age=11
getM.setQueryString(new NameValuePair[]{p1, p2});
try {
int code = httpClient.executeMethod(getM);
if (code == HttpStatus.SC_OK) {
// 获取结果字符串
String res = getM.getResponseBodyAsString();
// InputStream res = getM.getResponseBodyAsStream(); // 也可以转换为流
System.out.println(res);
} else {
System.err.println("请求失败,状态码:" + code);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
// 释放连接资源
getM.releaseConnection();
}
}
}
- HttpClient 4
import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.apache.http.client.utils.URIBuilder;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
public class HttpClient4 {
public static void main(String[] args) throws URISyntaxException {
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
// 创建一个URIBuilder来构建带参数的URL
URIBuilder uriBuilder = new URIBuilder("http://httpbin.org/get");
try {
// 添加参数
uriBuilder.addParameter("name", "zs");
uriBuilder.addParameter("age", "11");
// 构建最终的URI
URI uri = uriBuilder.build();
HttpGet httpGet = new HttpGet(uri);
// 设置请求配置(超时等)
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(2000) // 连接超时
.setConnectionRequestTimeout(2000) // 请求超时
.setSocketTimeout(2000) // 响应超时
.build();
httpGet.setConfig(requestConfig);
// 设置请求头(如果需要)
// httpGet.setHeader("Content-Type", "application/json"); // 注意:GET请求通常不需要Content-Type头
try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode == HttpStatus.SC_OK) {
HttpEntity entity = response.getEntity();
System.out.println(EntityUtils.toString(entity, "UTF-8"));
} else {
System.err.println("请求失败,状态码:" + statusCode);
}
} catch (IOException e) {
System.err.println("请求异常:" + e.getMessage());
}
} catch (URISyntaxException e) {
System.err.println("URI构建异常:" + e.getMessage());
}
}
}
Apache HttpClient 5
简介
Apache HttpClient 5 是一个开源的 HTTP 工具包,可以支持最新 HTTP 协议标准,且有丰富的 API 和强大的扩展特性,可以用于构建任何需要进行 HTTP 协议处理的应用程序。
下面将会介绍 Apache HttpClient 5 中最为常见的一些用法:
HttpClient 5 的 Get 请求、Post 请求、如何携带参数、JSON 参数、设置超时、异步请求、操作 Cookie、表单登录、基本认证、Digest 认证以及自定义 HTTP 请求拦截器等
依赖
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>
HttpClient 5 GET 请求
package com.jjy.httpclient5demo.test;
import org.apache.hc.client5.http.classic.methods.HttpGet; // 导入Apache HttpClient 5的HttpGet类,用于发送HTTP GET请求
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; // 导入CloseableHttpClient类,表示一个可关闭的HTTP客户端
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse; // 导入CloseableHttpResponse类,表示一个可关闭的HTTP响应
import org.apache.hc.client5.http.impl.classic.HttpClients; // 导入HttpClients类,用于创建HttpClient实例
import org.apache.hc.core5.http.HttpEntity; // 导入HttpEntity类,表示HTTP消息体
import org.apache.hc.core5.http.ParseException; // 导入ParseException类,表示HTTP消息解析异常
import org.apache.hc.core5.http.io.entity.EntityUtils; // 导入EntityUtils类,提供HTTP实体的工具方法
// 注意:下面的导入似乎是不相关的,因为该类并不是一个Servlet
// import javax.servlet.http.HttpServlet;
// import javax.servlet.http.HttpServletRequest;
import java.io.IOException; // 导入IO异常类
public class GetHttp5Client {
/**
* 发送GET请求并返回响应内容
*
* @param url 请求的URL
* @return 响应内容的字符串形式
*/
public static String get(String url) {
String resultContent = null; // 初始化响应内容的字符串为null
HttpGet httpGet = new HttpGet(url); // 创建HttpGet对象并设置请求的URL
try (CloseableHttpClient httpclient = HttpClients.createDefault()) { // 创建默认的CloseableHttpClient实例
try (CloseableHttpResponse response = httpclient.execute(httpGet)) { // 执行GET请求并获取响应
// 获取响应的状态信息
System.out.println(response.getVersion()); // 打印HTTP协议版本(例如: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) { // 捕获IO异常或HTTP消息解析异常
e.printStackTrace(); // 打印异常堆栈信息
}
return resultContent; // 返回响应内容的字符串
}
/**
* 主函数,程序的入口点
*
* @param args 命令行参数
*/
public static void main(String[] args) {
// 测试GET请求,注意这里的URL已经被注释掉了,实际使用时可以取消注释并替换成需要的URL
// String url = "http://localhost:8080/user/loginwithcode";
// String url = "https://api.fastgpt.in/api/v1/chat/completions";
String url = "http://httpbin.org/get"; // 使用的测试URL
String s = GetHttp5Client.get(url); // 调用get方法发送GET请求并获取响应内容
System.out.println(s); // 打印响应内容
}
}
响应信息:
HTTP/1.1
200
OK
{
"args": {},
"headers": {
"Accept-Encoding": "gzip, x-gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "Apache-HttpClient/5.1.3 (Java/17)",
"X-Amzn-Trace-Id": "Root=1-62bb1891-5ab5e5376ed960471bf32f17"
},
"origin": "47.251.4.198",
"url": "http://httpbin.org/get"
}
HttpClient 5 Fluent GET
使用 Apache HttpClient 5 提供的 Fluent API 可以更便捷的发起 GET 请求,但是可操作的地方较少。
依赖:
<!-- 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>
示例:
package com.jjy.httpclient5demo;
import java.io.IOException;
import org.apache.hc.client5.http.fluent.Request; // 导入Apache HttpClient 5的fluent API的Request类,用于构建HTTP请求
import org.apache.hc.client5.http.fluent.Response; // 导入Apache HttpClient 5的fluent API的Response类,用于处理HTTP响应
/**
* 使用Apache HttpClient 5的fluent API发送GET请求并获取响应内容
*
* @author zbxmx
*/
public class HttpClient5GetFluent {
/**
* 主函数,程序的入口点
*
* @param args 命令行参数
*/
public static void main(String[] args) {
// 调用get方法发送GET请求,并打印返回的响应内容
System.out.println(get("http://httpbin.org/get"));
}
/**
* 发送GET请求并返回响应内容
*
* @param url 请求的URL
* @return 响应内容的字符串形式
*/
public static String get(String url) {
String result = null; // 初始化响应内容的字符串为null
try {
// 使用fluent API构建GET请求并执行,获取响应对象
Response response = Request.get(url).execute();
// 从响应对象中获取响应内容,并转换为字符串
result = response.returnContent().asString();
} catch (IOException e) {
// 捕获IO异常,并打印异常堆栈信息
e.printStackTrace();
}
// 返回响应内容的字符串
return result;
}
}
HttpClient5 GET 请求参数
使用 URIBuilder 的 addParameters() 方法来构建 GET 请求的参数。
package com.jjy.httpclient5demo.test;
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;
/**
* 使用Apache HttpClient 5的经典API发送带有参数的GET请求并获取响应内容
*
* @author zbxmx
*/
public class HttpClient5GetParams {
/**
* 主函数,程序的入口点
*
* @param args 命令行参数
*/
public static void main(String[] args) {
// 调用get方法发送带有参数的GET请求,并打印返回的响应内容
String result = get("http://httpbin.org/get");
System.out.println(result);
}
/**
* 发送带有参数的GET请求并返回响应内容
*
* @param url 请求的URL
* @return 响应内容的字符串形式
*/
public static String get(String url) {
String resultContent = null;
// 创建HttpGet对象,设置请求的URL
HttpGet httpGet = new HttpGet(url);
// 创建存放表单参数的列表
List<NameValuePair> nvps = new ArrayList<>();
// 添加GET请求参数
nvps.add(new BasicNameValuePair("username", "wdbyte.com"));
nvps.add(new BasicNameValuePair("password", "secret"));
// 使用URIBuilder构建新的URI,将参数添加到请求URL中
try {
URI uri = new URIBuilder(new URI(url))
.addParameters(nvps) // 将参数添加到URL中
.build(); // 构建完整的URI
// 设置HttpGet对象的URI
httpGet.setUri(uri);
} catch (URISyntaxException e) {
// 如果URI构建出错,则抛出运行时异常
throw new RuntimeException(e);
}
try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
// 创建默认的HttpClient实例
try (CloseableHttpResponse response = httpclient.execute(httpGet)) {
// 使用HttpClient执行GET请求,获取响应对象
// 打印响应的HTTP版本、状态码和原因短语
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) {
// 捕获IO异常或解析异常,并打印异常堆栈信息
e.printStackTrace();
}
// 返回响应内容的字符串
return resultContent;
}
}
输出信息:
{
"args": {
"password": "secret",
"username": "wdbyte.com"
},
"headers": {
"Accept-Encoding": "gzip, x-gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "Apache-HttpClient/5.1.3 (Java/1.8.0_151)",
"X-Amzn-Trace-Id": "Root=1-62ecc660-69d58a226aefb1b6226541ec"
},
"origin": "218.26.154.94",
"url": "http://httpbin.org/get?username=wdbyte.com&password=secret"
}
HttpClient 5 POST 请求
下面演示发起一个 POST 请求,并携带表单参数。
package com.jjy.httpclient5demo.test;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
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;
/**
* 使用Apache HttpClient 5的经典API发送带有表单参数的POST请求并获取响应内容
*
* @author zbxmx
*/
public class HttpClient5Post {
/**
* 主函数,程序的入口点
*
* @param args 命令行参数
*/
public static void main(String[] args) {
// 调用post方法发送带有表单参数的POST请求,并打印返回的响应内容
String result = post("http://httpbin.org/post");
System.out.println(result);
}
/**
* 发送带有表单参数的POST请求并返回响应内容
*
* @param url 请求的URL
* @return 响应内容的字符串形式
*/
public static String post(String url) {
String result = null;
// 创建HttpPost对象,设置请求的URL
HttpPost httpPost = new HttpPost(url);
// 创建存放表单参数的列表
List<NameValuePair> nvps = new ArrayList<>();
// 添加POST请求参数
nvps.add(new BasicNameValuePair("username", "wdbyte.com"));
nvps.add(new BasicNameValuePair("password", "secret"));
// 创建UrlEncodedFormEntity,将表单参数添加到POST请求中
httpPost.setEntity(new UrlEncodedFormEntity(nvps));
try (CloseableHttpClient httpclient = HttpClients.createDefault()) {
// 创建默认的HttpClient实例
try (CloseableHttpResponse response = httpclient.execute(httpPost)) {
// 使用HttpClient执行POST请求,获取响应对象
// 打印响应的HTTP版本、状态码和原因短语
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) {
// 捕获IO异常,并打印异常堆栈信息
e.printStackTrace();
}
// 返回响应内容的字符串
return result;
}
}
输出结果:
{
"args": {},
"data": "",
"files": {},
"form": {
"password": "secret",
"username": "wdbyte.com"
},
"headers": {
"Accept-Encoding": "gzip, x-gzip, deflate",
"Content-Length": "35",
"Content-Type": "application/x-www-form-urlencoded; charset=ISO-8859-1",
"Host": "httpbin.org",
"User-Agent": "Apache-HttpClient/5.1.3 (Java/17.0.9)",
"X-Amzn-Trace-Id": "Root=1-660fe4f3-76d02ec05aa7a6535e833aad"
},
"json": null,
"origin": "218.26.154.94",
"url": "http://httpbin.org/post"
}
HttpClient 5 Fluent POST
使用 Apache HttpClient 5 提供的 Fluent API 可以更便捷的发起 POST 请求,但是可操作的地方较少。
package com.jjy.httpclient5demo.test;
import java.io.IOException;
import org.apache.hc.client5.http.fluent.Request;
import org.apache.hc.core5.http.message.BasicNameValuePair;
/**
* @author zbzmx
*/
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", "wdbyte.com"),
new BasicNameValuePair("password", "secret"));
try {
result = request.execute().returnContent().asString();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
}
HttpClient5 POST JSON 参数
package com.jjy.httpclient5demo.test;
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;
/**
* @author zbxmx
*/
public class HttpClient5PostWithJson {
public static void main(String[] args) {
String json = "{"
+ " \"password\": \"secret\","
+ " \"username\": \"wdbyte.com\""
+ "}";
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;
}
}
输出结果:
{
"args": {},
"data": "{ \"password\": \"secret\", \"username\": \"wdbyte.com\"}",
"files": {},
"form": {},
"headers": {
"Accept-Encoding": "gzip, x-gzip, deflate",
"Content-Length": "55",
"Content-Type": "application/json; charset=UTF-8",
"Host": "httpbin.org",
"User-Agent": "Apache-HttpClient/5.1.3 (Java/17.0.9)",
"X-Amzn-Trace-Id": "Root=1-660ff565-0afd9ffd3d41ed4417652ca1"
},
"json": {
"password": "secret",
"username": "wdbyte.com"
},
"origin": "218.26.154.94",
"url": "http://httpbin.org/post"
}
HttpClient 5 设置超时
使用 RequestConfig 对象来配置超时时间。
package com.jjy.httpclient5demo.test;
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;
/**
* @author zbxmx
*/
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;
}
}
HttpClient 5 异步请求
下面演示三种 HttpClient 5 异步请求方式。
package com.jjy.httpclient5demo.test;
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;
/**
* HttpClient 5 异步请求
* @author https://www.wdbyte.com
*
*/
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 clinet
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 clinet
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 clinet
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;
}
}
输出结果
getAsync1:/get->200
getAsync2:/get->200
getAsync3: 开始响应....
getAsync3: 收到数据....
getAsync3: 收到数据....
getAsync3: 收到数据....
getAsync3: 接收完毕...
getAsync3: /get->200
HttpClient 5 获取 Cookie
请求 http://httpbin.org/cookies/set/cookieName/www.wdbyte.com 的响应中会带有一个Cookie 信息,其中 name 为 cookieName,value 为 www.wdbyte.com,我们以此用作测试。
package com.jjy.httpclient5demo.test;
import java.util.List;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.cookie.BasicCookieStore;
import org.apache.hc.client5.http.cookie.Cookie;
import org.apache.hc.client5.http.cookie.CookieStore;
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.client5.http.impl.cookie.BasicClientCookie;
import org.apache.hc.client5.http.protocol.HttpClientContext;
import org.apache.hc.core5.http.io.entity.EntityUtils;
/**
* 这个例子演示了使用本地HTTP上下文填充, 自定义属性
*/
public class HttpClient5WithCookie {
public static void main(final String[] args) throws Exception {
try (final CloseableHttpClient httpclient = HttpClients.createDefault()) {
// 创建一个本地的 Cookie 存储
final CookieStore cookieStore = new BasicCookieStore();
// BasicClientCookie clientCookie = new BasicClientCookie("name", "www.wdbyte.com");
// clientCookie.setDomain("http://httpbin.org/cookies");
// 过期时间
// clientCookie.setExpiryDate(new Date());
// 添加到本地 Cookie
// cookieStore.addCookie(clientCookie);
// 创建本地 HTTP 请求上下文 HttpClientContext
final HttpClientContext localContext = HttpClientContext.create();
// 绑定 cookieStore 到 localContext
localContext.setCookieStore(cookieStore);
final HttpGet httpget = new HttpGet("http://httpbin.org/cookies/set/cookieName/www.wdbyte.com");
System.out.println("执行请求 " + httpget.getMethod() + " " + httpget.getUri());
// 获取 Coolie 信息
try (final CloseableHttpResponse response = httpclient.execute(httpget, localContext)) {
System.out.println("----------------------------------------");
System.out.println(response.getCode() + " " + response.getReasonPhrase());
final List<Cookie> cookies = cookieStore.getCookies();
for (int i = 0; i < cookies.size(); i++) {
System.out.println("Local cookie: " + cookies.get(i));
}
EntityUtils.consume(response.getEntity());
}
}
}
}
输出结果:
执行请求 GET http://httpbin.org/cookies/set/cookieName/www.wdbyte.com
----------------------------------------
200 OK
Local cookie: [name: cookieName; value: www.wdbyte.com; domain: httpbin.org; path: /; expiry: null]
HttpClient 5 读取文件内容请求
准备一个 JSON 内容格式的文件 params.json。
{"name":"www.wdbyte.com"}
读取这个文件作为请求参数发起请求。
package com.jjy.httpclient5demo.test;
import java.io.File;
import java.io.FileInputStream;
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.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.FileEntity;
import org.apache.hc.core5.http.io.entity.InputStreamEntity;
/**
* 加载数据流作为 POST 请求参数
*/
public class HttpClient5ChunkEncodedPost {
public static void main(final String[] args) throws Exception {
String params = "/Users/darcy/params.json";
try (final CloseableHttpClient httpclient = HttpClients.createDefault()) {
final HttpPost httppost = new HttpPost("http://httpbin.org/post");
final InputStreamEntity reqEntity = new InputStreamEntity(new FileInputStream(params), -1,
ContentType.APPLICATION_JSON);
// 也可以使用 FileEntity 的形式
// FileEntity reqEntity = new FileEntity(new File(params), ContentType.APPLICATION_JSON);
httppost.setEntity(reqEntity);
System.out.println("执行请求 " + httppost.getMethod() + " " + httppost.getUri());
try (final CloseableHttpResponse response = httpclient.execute(httppost)) {
System.out.println("----------------------------------------");
System.out.println(response.getCode() + " " + response.getReasonPhrase());
System.out.println(EntityUtils.toString(response.getEntity()));
}
}
}
}
输出结果
执行请求 POST http://httpbin.org/post
----------------------------------------
200 OK
{
"args": {},
"data": "{\"name\":\"www.wdbyte.com\"}\n",
"files": {},
"form": {},
"headers": {
"Accept-Encoding": "gzip, x-gzip, deflate",
"Content-Length": "26",
"Content-Type": "application/json; charset=UTF-8",
"Host": "httpbin.org",
"User-Agent": "Apache-HttpClient/5.1.3 (Java/1.8.0_151)",
"X-Amzn-Trace-Id": "Root=1-62ee4d95-1f956d4303cea09c52694c86"
},
"json": {
"name": "www.wdbyte.com"
},
"origin": "42.120.74.238",
"url": "http://httpbin.org/post"
}
HttpClient 5 表单登录
表单登录可以理解为发起一个携带了认证信息的请求,然后得到响应的 Cookie 的过程。当然这里不仅仅适用于表单登录,也可以是简单的发起一个携带了表单信息的请求。
本应该使用 POST 请求发送表单参数测试,但是在 httpbin.org 中没有对应的接口用于测试,所以这里换成了 GET 请求
package com.jjy.httpclient5demo.test;
import java.util.ArrayList;
import java.util.List;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.cookie.BasicCookieStore;
import org.apache.hc.client5.http.cookie.Cookie;
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.io.entity.EntityUtils;
import org.apache.hc.core5.http.message.BasicNameValuePair;
/**
* 演示基于表单的登录
*
* @author zbxmx
*/
public class HttpClient5FormLogin {
public static void main(final String[] args) throws Exception {
final BasicCookieStore cookieStore = new BasicCookieStore();
try (final CloseableHttpClient httpclient = HttpClients.custom()
.setDefaultCookieStore(cookieStore)
.build()) {
// 本应该使用 POST 请求发送表单参数,但是在 httpbin.org 中没有对应的接口用于测试,所以这里换成了 GET 请求
// HttpPost httpPost = new HttpPost("http://httpbin.org/cookies/set/username/wdbyte.com");
HttpGet httpPost = new HttpGet("http://httpbin.org/cookies/set/username/wdbyte.com");
// POST 表单请求参数
List<NameValuePair> nvps = new ArrayList<>();
nvps.add(new BasicNameValuePair("username", "wdbyte.com"));
nvps.add(new BasicNameValuePair("password", "secret"));
httpPost.setEntity(new UrlEncodedFormEntity(nvps));
try (final CloseableHttpResponse response2 = httpclient.execute(httpPost)) {
final HttpEntity entity = response2.getEntity();
System.out.println("Login form get: " + response2.getCode() + " " + response2.getReasonPhrase());
System.out.println("当前响应信息 "+EntityUtils.toString(entity));;
System.out.println("Post 登录 Cookie:");
final List<Cookie> cookies = cookieStore.getCookies();
if (cookies.isEmpty()) {
System.out.println("None");
} else {
for (int i = 0; i < cookies.size(); i++) {
System.out.println("- " + cookies.get(i));
}
}
}
}
}
}
输出结果:
Login form get: 200 OK
当前响应信息 {
"cookies": {
"username": "wdbyte.com"
}
}
Post 登录 Cookie:
- [name: username; value: wdbyte.com; domain: httpbin.org; path: /; expiry: null]
HttpClient 5 Basic Authorization
HTTP 基本认证(Basic Authorization)是一种比较简单的认证实现,主要流程如下
-
请求一个需要进行基本认证的 HTTP 接口,但是没有携带认证信息。
-
此时会响应 401 状态码,并在响应 header 中的 WWW-Authenticate 提示需要进行基本认证。
-
用户把需要提交认证信息进行冒号拼接,然后进行 base64 编码,再在得到的字符串开头拼接上 Basic 放入请求头 Authorization 中。
-
认证成功,响应成功。
你可以通过浏览器打开下面这个 URL 进行基本认证测试。
http://httpbin.org/basic-auth/admin/123456
package com.jjy.httpclient5demo.test;
import org.apache.hc.client5.http.auth.AuthScope;
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
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.io.entity.EntityUtils;
/**
* 一个简单的示例,它使用HttpClient执行HTTP请求;
* 一个需要进行用户身份验证的目标站点。
*/
public class HttpClient5BasicAuthentication {
public static void main(final String[] args) throws Exception {
final BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
new AuthScope("httpbin.org", 80),
new UsernamePasswordCredentials("admin", "123456".toCharArray()));
try (final CloseableHttpClient httpclient = HttpClients.custom()
.setDefaultCredentialsProvider(credsProvider)
.build()) {
final HttpGet httpget = new HttpGet("http://httpbin.org/basic-auth/admin/123456");
System.out.println("执行请求" + httpget.getMethod() + " " + httpget.getUri());
try (final CloseableHttpResponse response = httpclient.execute(httpget)) {
System.out.println("----------------------------------------");
System.out.println(response.getCode() + " " + response.getReasonPhrase());
System.out.println(EntityUtils.toString(response.getEntity()));
}
}
}
}
输出结果
执行请求GET http://httpbin.org/basic-auth/user/passwd
----------------------------------------
200 OK
{
"authenticated": true,
"user": "user"
}
HttpClient 5 Digest Authorization
HTTP Basic Authorization 的缺点显而易见,密码通过明文传输存在一定的安全风险,Digest Authorization 认证方式解决了明文传输的问题,这里不过多介绍 Digest 的相关内容,通过一个图简单的示意 Digest 认证方式的流程。
package com.jjy.httpclient5demo.test;
import org.apache.hc.client5.http.auth.AuthExchange;
import org.apache.hc.client5.http.auth.AuthScheme;
import org.apache.hc.client5.http.auth.AuthScope;
import org.apache.hc.client5.http.auth.UsernamePasswordCredentials;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider;
import org.apache.hc.client5.http.impl.auth.DigestScheme;
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.client5.http.protocol.HttpClientContext;
import org.apache.hc.core5.http.HttpHost;
import org.apache.hc.core5.http.io.entity.EntityUtils;
/**
*
* HttpClient如何验证多个请求的示例
* 使用相同的摘要方案。在初始请求/响应交换之后
* 共享相同执行上下文的所有后续请求都可以重用
* 要向服务器进行身份验证的最后一个摘要nonce值。
*/
public class HttpClient5PreemptiveDigestAuthentication {
public static void main(final String[] args) throws Exception {
try (final CloseableHttpClient httpclient = HttpClients.createDefault()) {
final HttpHost target = new HttpHost("http", "httpbin.org", 80);
final HttpClientContext localContext = HttpClientContext.create();
final BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(
new AuthScope(target),
new UsernamePasswordCredentials("admin", "123456".toCharArray()));
localContext.setCredentialsProvider(credentialsProvider);
final HttpGet httpget = new HttpGet("http://httpbin.org/digest-auth/auth/admin/123456");
System.out.println("执行请求 " + httpget.getMethod() + " " + httpget.getUri());
for (int i = 0; i < 2; i++) {
try (final CloseableHttpResponse response = httpclient.execute(target, httpget, localContext)) {
System.out.println("----------------------------------------");
System.out.println(response.getCode() + " " + response.getReasonPhrase());
EntityUtils.consume(response.getEntity());
final AuthExchange authExchange = localContext.getAuthExchange(target);
if (authExchange != null) {
final AuthScheme authScheme = authExchange.getAuthScheme();
if (authScheme instanceof DigestScheme) {
final DigestScheme digestScheme = (DigestScheme) authScheme;
System.out.println("Nonce: " + digestScheme.getNonce() +
"; count: " + digestScheme.getNounceCount());
}
}
}
}
}
}
}
HttpClient 5 拦截器
HttpClient 5 中的拦截器可以对请求过程的各个阶段进行拦截处理,通过 HttpClientBuilder 中的关于 Interceptor 的方法可以看到可以
HttpClient5 拦截器
下面编写一个示例,发起三次请求,每次请求都在请求头 herader 中增加一个 request-id 参数,然后对 request-id 值为 2 的请求直接响应 404 结束。
package com.jjy.httpclient5demo.test;
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.HttpEntity;
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()));
}
}
}
}
}
输出结果文章来源:https://www.toymoban.com/news/detail-848211.html
----------------------------------------
执行请求 GET http://httpbin.org/get
200 OK
{
"args": {},
"headers": {
"Accept-Encoding": "gzip, x-gzip, deflate",
"Host": "httpbin.org",
"Request-Id": "1",
"User-Agent": "Apache-HttpClient/5.1.3 (Java/1.8.0_151)",
"X-Amzn-Trace-Id": "Root=1-62f615ba-658ccd42182d22534dbba82c"
},
"origin": "42.120.75.221",
"url": "http://httpbin.org/get"
}
----------------------------------------
执行请求 GET http://httpbin.org/get
404 Oppsie
bad luck
----------------------------------------
执行请求 GET http://httpbin.org/get
200 OK
{
"args": {},
"headers": {
"Accept-Encoding": "gzip, x-gzip, deflate",
"Host": "httpbin.org",
"Request-Id": "3",
"User-Agent": "Apache-HttpClient/5.1.3 (Java/1.8.0_151)",
"X-Amzn-Trace-Id": "Root=1-62f615bb-4eb6ba10736ace0e21d0cb8c"
},
"origin": "42.120.75.221",
"url": "http://httpbin.org/get"
}
如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,大家的支持就是我坚持下去的动力
文章来源地址https://www.toymoban.com/news/detail-848211.html
到了这里,关于4.5日学习打卡----学习Apache HttpClient 5的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!