Skip to content

Commit baf53dc

Browse files
kakotorbinarywang
authored andcommitted
DefaultApacheHttpClientBuilder修改为单例模式 (#310)
1 parent 56557bf commit baf53dc

File tree

2 files changed

+81
-6
lines changed

2 files changed

+81
-6
lines changed

weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/DefaultApacheHttpClientBuilder.java

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,16 @@ public boolean retryRequest(IOException exception, int executionCount, HttpConte
6868
* 闲置连接监控线程
6969
*/
7070
private IdleConnectionMonitorThread idleConnectionMonitorThread;
71-
private HttpClientBuilder httpClientBuilder;
71+
/**
72+
* 持有client对象,仅初始化一次,避免多service实例的时候造成重复初始化的问题
73+
*/
74+
private CloseableHttpClient closeableHttpClient;
7275

7376
private DefaultApacheHttpClientBuilder() {
7477
}
7578

7679
public static DefaultApacheHttpClientBuilder get() {
77-
return new DefaultApacheHttpClientBuilder();
80+
return DefaultApacheHttpClientBuilder.SingletonHolder.INSTANCE;
7881
}
7982

8083
@Override
@@ -219,7 +222,7 @@ private synchronized void prepare() {
219222
this.idleConnectionMonitorThread.setDaemon(true);
220223
this.idleConnectionMonitorThread.start();
221224

222-
this.httpClientBuilder = HttpClients.custom()
225+
HttpClientBuilder httpClientBuilder = HttpClients.custom()
223226
.setConnectionManager(connectionManager)
224227
.setConnectionManagerShared(true)
225228
.setSSLSocketFactory(this.buildSSLConnectionSocketFactory())
@@ -240,12 +243,13 @@ private synchronized void prepare() {
240243
new AuthScope(this.httpProxyHost, this.httpProxyPort),
241244
new UsernamePasswordCredentials(this.httpProxyUsername,
242245
this.httpProxyPassword));
243-
this.httpClientBuilder.setDefaultCredentialsProvider(provider);
246+
httpClientBuilder.setDefaultCredentialsProvider(provider);
244247
}
245248

246249
if (StringUtils.isNotBlank(this.userAgent)) {
247-
this.httpClientBuilder.setUserAgent(this.userAgent);
250+
httpClientBuilder.setUserAgent(this.userAgent);
248251
}
252+
this.closeableHttpClient = httpClientBuilder.build();
249253
prepared.set(true);
250254
}
251255

@@ -277,7 +281,14 @@ public CloseableHttpClient build() {
277281
if (!prepared.get()) {
278282
prepare();
279283
}
280-
return this.httpClientBuilder.build();
284+
return this.closeableHttpClient;
285+
}
286+
287+
/**
288+
* DefaultApacheHttpClientBuilder 改为单例模式,并持有唯一的CloseableHttpClient(仅首次调用创建)
289+
*/
290+
private static class SingletonHolder {
291+
private static final DefaultApacheHttpClientBuilder INSTANCE = new DefaultApacheHttpClientBuilder();
281292
}
282293

283294
public static class IdleConnectionMonitorThread extends Thread {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package me.chanjar.weixin.common.util.http.apache;
2+
3+
import org.apache.http.client.methods.CloseableHttpResponse;
4+
import org.apache.http.client.methods.HttpGet;
5+
import org.apache.http.impl.client.CloseableHttpClient;
6+
import org.testng.Assert;
7+
import org.testng.annotations.Test;
8+
9+
import java.io.IOException;
10+
import java.util.ArrayList;
11+
import java.util.List;
12+
13+
public class DefaultApacheHttpClientBuilderTest {
14+
@Test
15+
public void testBuild() throws Exception {
16+
DefaultApacheHttpClientBuilder builder1 = DefaultApacheHttpClientBuilder.get();
17+
DefaultApacheHttpClientBuilder builder2 = DefaultApacheHttpClientBuilder.get();
18+
Assert.assertSame(builder1, builder2, "DefaultApacheHttpClientBuilder为单例,获取到的对象应该相同");
19+
List<TestThread> threadList = new ArrayList<>(10);
20+
for (int i = 0; i < 10; i++) {
21+
TestThread thread = new TestThread();
22+
thread.start();
23+
threadList.add(thread);
24+
}
25+
for (TestThread testThread : threadList) {
26+
testThread.join();
27+
Assert.assertNotEquals(-1,testThread.getRespState(),"请求响应code不应为-1");
28+
}
29+
30+
for (int i = 1; i < threadList.size(); i++) {
31+
TestThread thread1 = threadList.get(i - 1);
32+
TestThread thread2 = threadList.get(i);
33+
Assert.assertSame(
34+
thread1.getClient(),
35+
thread2.getClient(),
36+
"DefaultApacheHttpClientBuilder为单例,并持有了相同的HttpClient"
37+
);
38+
}
39+
}
40+
41+
42+
public static class TestThread extends Thread {
43+
private CloseableHttpClient client;
44+
private int respState = -1;
45+
46+
@Override
47+
public void run() {
48+
client = DefaultApacheHttpClientBuilder.get().build();
49+
HttpGet httpGet = new HttpGet("http://www.sina.com.cn/");
50+
try (CloseableHttpResponse resp = client.execute(httpGet)){
51+
respState = resp.getStatusLine().getStatusCode();
52+
} catch (IOException ignored) {
53+
}
54+
}
55+
56+
public CloseableHttpClient getClient() {
57+
return client;
58+
}
59+
60+
public int getRespState() {
61+
return respState;
62+
}
63+
}
64+
}

0 commit comments

Comments
 (0)