HttpClient单元测试

pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>cn.idea360</groupId>
<artifactId>httpclient-demo</artifactId>
<version>1.0.0</version>

<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>

<dependencies>
<!-- junit5 -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.9.0</version>
<scope>test</scope>
</dependency>
<!-- log4j2日志门面 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.19.0</version>
</dependency>
<!-- log4j2日志实现-->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.19.0</version>
</dependency>
<!-- 导入slf4j日志门面依赖 -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.36</version>
</dependency>
<!-- log4j适配器 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.19.0</version>
<scope>test</scope>
</dependency>
<!-- httpclient debug -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>
<version>1.7.5</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.12.0</version>
</dependency>
</dependencies>
</project>

log4j2.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version="1.0" encoding="UTF-8" ?>
<Configuration>
<Properties>
<!--自定义一些常量,之后使用${变量名}引用-->
<property name="charset">UTF-8</property>
</Properties>
<Appenders>
<!--控制台输出 这个name属性不可以改变-->
<!--console :控制台输出的配置-->
<console name="consoleAppender" target="SYSTEM_OUT">
<!--控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch)-->
<ThresholdFilter level="debug" onMatch="ACCEPT" onMismatch="DENY"/>
<!--输出格式-->
<PatternLayout pattern="[%d{YYYY-MM-dd HH:mm:ss:SSS}] [%p] - %l - %m%n" charset="${charset}"/>
</console>
</Appenders>
<!--配置logger-->
<Loggers>
<!--指定包输出level级别信息, 受Appenders中配置的level约束-->
<logger name="cn.idea360.httpclient" level="debug"/>
<logger name="org.apache.http" level="debug"/>
<!--配置rootlogger, 项目的根日志, 如果没有单独指定Logger, 那么就会默认使用该Root日志输出-->
<Root level="info">
<!--引用Appender-->
<AppenderRef ref="consoleAppender"/>
</Root>
</Loggers>
</Configuration>

单元测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
package cn.idea360.httpclient;

import org.apache.http.HttpEntity;
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.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.function.Consumer;

import static org.apache.http.HttpStatus.SC_OK;
import static org.junit.jupiter.api.Assertions.assertEquals;

/**
* @author cuishiying
*/
public class ApacheHttpClientUnitTest {

private final Logger log = LoggerFactory.getLogger(this.getClass());
public static final String DUMMY_URL = "https://postman-echo.com/get";
// 请求总数
public static final int clientTotal = 5000;
// 同时并发执行的线程数
public static final int threadTotal = 200;

@FunctionalInterface
public interface RequestBuilder {
void execute(int concurrency, int clientTotal);
}

private RequestBuilder testFunction() {
return (concurrency, clientTotal) -> {
log.info("test function: {}, {}", concurrency, clientTotal);
};
}

public Consumer<String> testConsumer() {
return url -> log.info("url: {}", url);
}

/**
* 模拟并发请求
*/
void executeConcurrentRequest(int concurrency, int clientTotal, Consumer<String> request) throws Exception {
long start = System.currentTimeMillis();
// 线程池
ExecutorService executorService = Executors.newCachedThreadPool();
// 控制并发
final Semaphore semaphore = new Semaphore(threadTotal);
// 闭锁(让主线程等待子线程5000个任务执行完毕)
final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);
for (int i = 0; i < clientTotal ; i++) {
executorService.execute(() -> {
try {
// 此处能够同时获取200个令牌, 然后等待令牌释放
semaphore.acquire();
// request请求
request.accept(DUMMY_URL);
// 令牌释放后其他任务才能继续执行, 直到5000任务执行完毕
semaphore.release();
} catch (Exception e) {
log.error("exception", e);
}
// 计数器-1
countDownLatch.countDown();
});
}
// 阻塞主线程, 等待子线程执行完毕(countDownLatch计数器变为0)
countDownLatch.await();
executorService.shutdown();
log.info("time consuming: {}ms", System.currentTimeMillis()-start);
}

@Test
void simpleTest() throws Exception {
// executeConcurrentRequest(1, 1, testConsumer());
// executeConcurrentRequest(1, 1, whenUseApacheHttpClient_thenCorrect());
// executeConcurrentRequest(1, 1, testUnCompleteConsumerAndNoCloseResponse());
// executeConcurrentRequest(1, 1, testCompleteConsumerAndNoCloseResponse());
executeConcurrentRequest(1, 1, testCompleteConsumerAndCloseResponse());
}

/**
* 工厂build {@link HttpClientBuilder#build()}
* 可以看到默认创建的是 PoolingHttpClientConnectionManager
*
* 部分日志如下,方便理解http请求过程
* [2022-10-30 11:19:47:470] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.requestConnection(PoolingHttpClientConnectionManager.java:267) - Connection request: [route: {s}->https://postman-echo.com:443][total available: 0; route allocated: 0 of 2; total allocated: 0 of 20]
* [2022-10-30 11:19:47:484] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.leaseConnection(PoolingHttpClientConnectionManager.java:312) - Connection leased: [id: 0][route: {s}->https://postman-echo.com:443][total available: 0; route allocated: 1 of 2; total allocated: 1 of 20]
* [2022-10-30 11:19:47:486] [DEBUG] - org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:234) - Opening connection {s}->https://postman-echo.com:443
* [2022-10-30 11:19:47:750] [DEBUG] - org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:139) - Connecting to postman-echo.com/34.192.131.198:443
* [2022-10-30 11:19:47:751] [DEBUG] - org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:366) - Connecting socket to postman-echo.com/34.192.131.198:443 with timeout 0
* [2022-10-30 11:19:48:030] [DEBUG] - org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:435) - Starting handshake
* [2022-10-30 11:19:48:735] [DEBUG] - org.apache.http.conn.ssl.SSLConnectionSocketFactory.verifyHostname(SSLConnectionSocketFactory.java:465) - Secure session established
* [2022-10-30 11:19:48:752] [DEBUG] - org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:146) - Connection established 10.10.0.110:64107<->34.192.131.198:443
* [2022-10-30 11:19:48:753] [DEBUG] - org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:255) - Executing request GET /get HTTP/1.1
* [2022-10-30 11:19:49:050] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.releaseConnection(PoolingHttpClientConnectionManager.java:344) - Connection [id: 0][route: {s}->https://postman-echo.com:443] can be kept alive indefinitely
* [2022-10-30 11:19:49:050] [DEBUG] - org.apache.http.impl.conn.LoggingManagedHttpClientConnection.setSocketTimeout(LoggingManagedHttpClientConnection.java:88) - http-outgoing-0: set socket timeout to 0
* [2022-10-30 11:19:49:051] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.releaseConnection(PoolingHttpClientConnectionManager.java:351) - Connection released: [id: 0][route: {s}->https://postman-echo.com:443][total available: 1; route allocated: 1 of 2; total allocated: 1 of 20]
* [2022-10-30 11:19:49:054] [DEBUG] - cn.idea360.httpclient.ApacheHttpClientUnitTest.lambda$whenUseApacheHttpClient_thenCorrect$3(ApacheHttpClientUnitTest.java:104) - Response -> {"args":{},"headers":{"x-forwarded-proto":"https","x-forwarded-port":"443","host":"postman-echo.com","x-amzn-trace-id":"Root=1-635ded56-731bb1d3396ac8a649e865fe","user-agent":"Apache-HttpClient/4.5.13 (Java/11.0.9)","accept-encoding":"gzip,deflate"},"url":"https://postman-echo.com/get"}
* [2022-10-30 11:19:49:054] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.shutdown(PoolingHttpClientConnectionManager.java:411) - Connection manager is shutting down
* [2022-10-30 11:19:49:055] [DEBUG] - org.apache.http.impl.conn.LoggingManagedHttpClientConnection.close(LoggingManagedHttpClientConnection.java:79) - http-outgoing-0: Close connection
* [2022-10-30 11:19:49:058] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.shutdown(PoolingHttpClientConnectionManager.java:434) - Connection manager shut down
*/
public Consumer<String> whenUseApacheHttpClient_thenCorrect() {
return url -> {
HttpGet request = new HttpGet(url);
try (CloseableHttpClient client = HttpClients.createDefault(); CloseableHttpResponse response = client.execute(request)) {
HttpEntity entity = response.getEntity();
assertEquals(SC_OK, response.getStatusLine().getStatusCode());
String body = EntityUtils.toString(entity);
log.debug("Response -> {}", body);
} catch (Exception e) {
e.printStackTrace();
}
};
}

/**
* @return 自定义HTTP客户端
*/
CloseableHttpClient buildCustomConnectionPool() {
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(5 * 1000) // 连接超时
.setConnectionRequestTimeout(5 * 1000) // 返回从连接管理器请求连接时使用的超时时间
.setSocketTimeout(5 * 1000) // 读取数据超时
.build();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager();
return HttpClients.custom()
.setConnectionManager(connectionManager)
.setDefaultRequestConfig(requestConfig)
.build();
}

/**
* 设置超时, 并做1个完整的HTTP请求示例, 并释放资源
*/
void setRequestConfigAndGetRequest() {
CloseableHttpClient httpClient = HttpClients.createDefault();
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(5 * 1000)
.setConnectionRequestTimeout(5 * 1000)
.setSocketTimeout(5 * 1000)
.build();
HttpGet httpGet = new HttpGet(DUMMY_URL);
httpGet.setConfig(requestConfig);
httpGet.setHeader(new BasicHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"));
httpGet.setHeader(new BasicHeader("Accept", "text/plain;charset=utf-8"));
CloseableHttpResponse response = null;
try {
response = httpClient.execute(httpGet);
// 判断响应码
if (response.getStatusLine().getStatusCode() == SC_OK) {
HttpEntity entity = response.getEntity();
// 使用工具类EntityUtils 从响应中读取内容
String result = EntityUtils.toString(entity, "utf-8");
System.out.println(result);
}

} catch (Exception e) {
System.out.print("http GET 请求异常" + e);
} finally {
// 释放资源
try {
if (response != null) {
response.close();
}
} catch (IOException e) {
System.out.print("关闭流异常" + e);
}
// 关闭客户端.会先关闭客户端中的所有连接,然后销毁客户端。
try {
httpClient.close();
} catch (IOException e) {
System.out.print("关闭HttpClient异常" + e);
}
}
}

/**
* 消费不彻底. 对于response消费不彻底,没有进行关闭
*
* 第一次连接:连接无法被复用,kept alive 0,同时占用了一个route。
* [2022-10-30 12:41:41:094] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.requestConnection(PoolingHttpClientConnectionManager.java:267) - Connection request: [route: {s}->https://postman-echo.com:443][total available: 0; route allocated: 0 of 2; total allocated: 0 of 20]
* [2022-10-30 12:41:41:115] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.leaseConnection(PoolingHttpClientConnectionManager.java:312) - Connection leased: [id: 0][route: {s}->https://postman-echo.com:443][total available: 0; route allocated: 1 of 2; total allocated: 1 of 20]
*
* 第二次连接:连接无法被复用,kept alive 0,相同的IP和请求路由,又占用了一个route。
* [2022-10-30 12:41:42:796] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.requestConnection(PoolingHttpClientConnectionManager.java:267) - Connection request: [route: {s}->https://postman-echo.com:443][total available: 0; route allocated: 1 of 2; total allocated: 1 of 20]
* [2022-10-30 12:41:42:797] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.leaseConnection(PoolingHttpClientConnectionManager.java:312) - Connection leased: [id: 1][route: {s}->https://postman-echo.com:443][total available: 0; route allocated: 2 of 2; total allocated: 2 of 20]
*
* 第三次连接:相同的IP和请求路由,由于默认配置中:httpClient.connManager.pool.defaultMaxPerRoute = 2(相同的请求路径最多可以同时存在2个),没有可用的route此时就会一直等待原连接的释放,获取到route之后才可以进行连接。
* [2022-10-30 12:41:43:805] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.requestConnection(PoolingHttpClientConnectionManager.java:267) - Connection request: [route: {s}->https://postman-echo.com:443][total available: 0; route allocated: 2 of 2; total allocated: 2 of 20]
*/
Consumer<String> testUnCompleteConsumerAndNoCloseResponse() {
return url -> {
// 创建http client客户端
CloseableHttpClient httpClient = HttpClients.createDefault();
// 创建http GET请求
HttpGet httpGet = new HttpGet(url);
// 设置请求头部编码
httpGet.setHeader(new BasicHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"));
// 设置返回编码
httpGet.setHeader(new BasicHeader("Accept", "text/plain;charset=utf-8"));

for (int i = 0; i < 3; i++) {
// 返回响应
CloseableHttpResponse response = null;
try {
response = httpClient.execute(httpGet);
} catch (Exception e) {
System.out.print("http GET 请求异常" + e);
}
}
};
}

/**
* 第一次连接:total kept alive: 1,连接可以被复用
* [2022-10-31 23:44:12:773] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.requestConnection(PoolingHttpClientConnectionManager.java:267) - Connection request: [route: {s}->https://postman-echo.com:443][total available: 0; route allocated: 0 of 2; total allocated: 0 of 20]
* [2022-10-31 23:44:12:786] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.leaseConnection(PoolingHttpClientConnectionManager.java:312) - Connection leased: [id: 0][route: {s}->https://postman-echo.com:443][total available: 0; route allocated: 1 of 2; total allocated: 1 of 20]
* [2022-10-31 23:44:12:788] [DEBUG] - org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:234) - Opening connection {s}->https://postman-echo.com:443
* [2022-10-31 23:44:14:381] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.releaseConnection(PoolingHttpClientConnectionManager.java:344) - Connection [id: 0][route: {s}->https://postman-echo.com:443] can be kept alive indefinitely
* [2022-10-31 23:44:14:382] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.releaseConnection(PoolingHttpClientConnectionManager.java:351) - Connection released: [id: 0][route: {s}->https://postman-echo.com:443][total available: 1; route allocated: 1 of 2; total allocated: 1 of 20]
*
* 第二次连接:虽然有一个连接可以复用,但是在尝试复用的时候,发现该通道对应的流并没有关闭,无法使用,所以在关闭了该连接后,重新生成了一个
* [2022-10-31 23:44:14:386] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.requestConnection(PoolingHttpClientConnectionManager.java:267) - Connection request: [route: {s}->https://postman-echo.com:443][total available: 1; route allocated: 1 of 2; total allocated: 1 of 20]
* [2022-10-31 23:44:14:386] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.leaseConnection(PoolingHttpClientConnectionManager.java:312) - Connection leased: [id: 0][route: {s}->https://postman-echo.com:443][total available: 0; route allocated: 1 of 2; total allocated: 1 of 20]
* [2022-10-31 23:44:14:645] [DEBUG] - org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:285) - Connection can be kept alive indefinitely
* [2022-10-31 23:44:14:647] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.releaseConnection(PoolingHttpClientConnectionManager.java:344) - Connection [id: 0][route: {s}->https://postman-echo.com:443] can be kept alive indefinitely
* [2022-10-31 23:44:14:648] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.releaseConnection(PoolingHttpClientConnectionManager.java:351) - Connection released: [id: 0][route: {s}->https://postman-echo.com:443][total available: 1; route allocated: 1 of 2; total allocated: 1 of 20]
*
* 第三次连接:与第二次相同
* [2022-10-31 23:44:14:652] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.requestConnection(PoolingHttpClientConnectionManager.java:267) - Connection request: [route: {s}->https://postman-echo.com:443][total available: 1; route allocated: 1 of 2; total allocated: 1 of 20]
* [2022-10-31 23:44:14:652] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.leaseConnection(PoolingHttpClientConnectionManager.java:312) - Connection leased: [id: 0][route: {s}->https://postman-echo.com:443][total available: 0; route allocated: 1 of 2; total allocated: 1 of 20]
* [2022-10-31 23:44:14:886] [DEBUG] - org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:285) - Connection can be kept alive indefinitely
* [2022-10-31 23:44:14:890] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.releaseConnection(PoolingHttpClientConnectionManager.java:344) - Connection [id: 0][route: {s}->https://postman-echo.com:443] can be kept alive indefinitely
* [2022-10-31 23:44:14:891] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.releaseConnection(PoolingHttpClientConnectionManager.java:351) - Connection released: [id: 0][route: {s}->https://postman-echo.com:443][total available: 1; route allocated: 1 of 2; total allocated: 1 of 20]
*/
Consumer<String> testCompleteConsumerAndNoCloseResponse() {
return url -> {
// 创建http client客户端
CloseableHttpClient httpClient = HttpClients.createDefault();
// 创建http GET请求
HttpGet httpGet = new HttpGet(url);
// 设置请求头部编码
httpGet.setHeader(new BasicHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"));
// 设置返回编码
httpGet.setHeader(new BasicHeader("Accept", "text/plain;charset=utf-8"));

for (int i = 0; i < 3; i++) {
// 返回响应
CloseableHttpResponse response = null;
try {
response = httpClient.execute(httpGet);
// 判断响应码
if (response.getStatusLine().getStatusCode() == SC_OK) {
HttpEntity entity = response.getEntity();
// 使用工具类EntityUtils 从响应中读取内容
String result = EntityUtils.toString(entity, "utf-8");
System.out.println(result);
}
} catch (Exception e) {
System.out.print("http GET 请求异常" + e);
}
}
};
}

/**
* 第一次连接:total kept alive: 1,连接可以被复用
* [2022-10-31 23:58:26:083] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.requestConnection(PoolingHttpClientConnectionManager.java:267) - Connection request: [route: {s}->https://postman-echo.com:443][total available: 0; route allocated: 0 of 2; total allocated: 0 of 20]
* [2022-10-31 23:58:26:094] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.leaseConnection(PoolingHttpClientConnectionManager.java:312) - Connection leased: [id: 0][route: {s}->https://postman-echo.com:443][total available: 0; route allocated: 1 of 2; total allocated: 1 of 20]
* [2022-10-31 23:58:26:095] [DEBUG] - org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:234) - Opening connection {s}->https://postman-echo.com:443
* [2022-10-31 23:58:28:714] [DEBUG] - org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:285) - Connection can be kept alive indefinitely
* [2022-10-31 23:58:28:733] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.releaseConnection(PoolingHttpClientConnectionManager.java:344) - Connection [id: 0][route: {s}->https://postman-echo.com:443] can be kept alive indefinitely
* [2022-10-31 23:58:28:736] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.releaseConnection(PoolingHttpClientConnectionManager.java:351) - Connection released: [id: 0][route: {s}->https://postman-echo.com:443][total available: 1; route allocated: 1 of 2; total allocated: 1 of 20]
*
* 第二、三次连接:可以复用之前的连接,也不会增加新的route和allocated
* [2022-10-31 23:58:28:740] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.requestConnection(PoolingHttpClientConnectionManager.java:267) - Connection request: [route: {s}->https://postman-echo.com:443][total available: 1; route allocated: 1 of 2; total allocated: 1 of 20]
* [2022-10-31 23:58:28:741] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.leaseConnection(PoolingHttpClientConnectionManager.java:312) - Connection leased: [id: 0][route: {s}->https://postman-echo.com:443][total available: 0; route allocated: 1 of 2; total allocated: 1 of 20]
* [2022-10-31 23:58:29:066] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.releaseConnection(PoolingHttpClientConnectionManager.java:344) - Connection [id: 0][route: {s}->https://postman-echo.com:443] can be kept alive indefinitely
* [2022-10-31 23:58:29:067] [DEBUG] - org.apache.http.impl.conn.PoolingHttpClientConnectionManager.releaseConnection(PoolingHttpClientConnectionManager.java:351) - Connection released: [id: 0][route: {s}->https://postman-echo.com:443][total available: 1; route allocated: 1 of 2; total allocated: 1 of 20]
*/
Consumer<String> testCompleteConsumerAndCloseResponse() {
return url -> {
// 创建http client客户端
CloseableHttpClient httpClient = HttpClients.createDefault();
// 创建http GET请求
HttpGet httpGet = new HttpGet(url);
// 设置请求头部编码
httpGet.setHeader(new BasicHeader("Content-Type", "application/x-www-form-urlencoded; charset=utf-8"));
// 设置返回编码
httpGet.setHeader(new BasicHeader("Accept", "text/plain;charset=utf-8"));

for (int i = 0; i < 3; i++) {
// 返回响应
CloseableHttpResponse response = null;
try {
response = httpClient.execute(httpGet);
// 判断响应码
if (response.getStatusLine().getStatusCode() == SC_OK) {
HttpEntity entity = response.getEntity();
// 使用工具类EntityUtils 从响应中读取内容
String result = EntityUtils.toString(entity, "utf-8");
System.out.println(result);
}
} catch (Exception e) {
System.out.print("http GET 请求异常" + e);
} finally {
try {
if (response != null) {
response.close();
}
} catch (IOException e) {
System.out.print("关闭流异常" + e);
}
}
}
};
}
}

参考