From 6ce585f2460f01c42b2ec2f8161004f1a4f4128f Mon Sep 17 00:00:00 2001 From: kakotor Date: Thu, 10 Aug 2017 12:25:10 +0800 Subject: [PATCH] =?UTF-8?q?DefaultApacheHttpClientBuilder=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=E5=8D=95=E4=BE=8B=E6=A8=A1=E5=BC=8F=20(#310)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DefaultApacheHttpClientBuilder.java | 23 +++++-- .../DefaultApacheHttpClientBuilderTest.java | 64 +++++++++++++++++++ 2 files changed, 81 insertions(+), 6 deletions(-) create mode 100644 weixin-java-common/src/test/java/me/chanjar/weixin/common/util/http/apache/DefaultApacheHttpClientBuilderTest.java diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/DefaultApacheHttpClientBuilder.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/DefaultApacheHttpClientBuilder.java index b328ede9..19c79bdc 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/DefaultApacheHttpClientBuilder.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/apache/DefaultApacheHttpClientBuilder.java @@ -68,13 +68,16 @@ public class DefaultApacheHttpClientBuilder implements ApacheHttpClientBuilder { * 闲置连接监控线程 */ private IdleConnectionMonitorThread idleConnectionMonitorThread; - private HttpClientBuilder httpClientBuilder; + /** + * 持有client对象,仅初始化一次,避免多service实例的时候造成重复初始化的问题 + */ + private CloseableHttpClient closeableHttpClient; private DefaultApacheHttpClientBuilder() { } public static DefaultApacheHttpClientBuilder get() { - return new DefaultApacheHttpClientBuilder(); + return DefaultApacheHttpClientBuilder.SingletonHolder.INSTANCE; } @Override @@ -219,7 +222,7 @@ public class DefaultApacheHttpClientBuilder implements ApacheHttpClientBuilder { this.idleConnectionMonitorThread.setDaemon(true); this.idleConnectionMonitorThread.start(); - this.httpClientBuilder = HttpClients.custom() + HttpClientBuilder httpClientBuilder = HttpClients.custom() .setConnectionManager(connectionManager) .setConnectionManagerShared(true) .setSSLSocketFactory(this.buildSSLConnectionSocketFactory()) @@ -240,12 +243,13 @@ public class DefaultApacheHttpClientBuilder implements ApacheHttpClientBuilder { new AuthScope(this.httpProxyHost, this.httpProxyPort), new UsernamePasswordCredentials(this.httpProxyUsername, this.httpProxyPassword)); - this.httpClientBuilder.setDefaultCredentialsProvider(provider); + httpClientBuilder.setDefaultCredentialsProvider(provider); } if (StringUtils.isNotBlank(this.userAgent)) { - this.httpClientBuilder.setUserAgent(this.userAgent); + httpClientBuilder.setUserAgent(this.userAgent); } + this.closeableHttpClient = httpClientBuilder.build(); prepared.set(true); } @@ -277,7 +281,14 @@ public class DefaultApacheHttpClientBuilder implements ApacheHttpClientBuilder { if (!prepared.get()) { prepare(); } - return this.httpClientBuilder.build(); + return this.closeableHttpClient; + } + + /** + * DefaultApacheHttpClientBuilder 改为单例模式,并持有唯一的CloseableHttpClient(仅首次调用创建) + */ + private static class SingletonHolder { + private static final DefaultApacheHttpClientBuilder INSTANCE = new DefaultApacheHttpClientBuilder(); } public static class IdleConnectionMonitorThread extends Thread { diff --git a/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/http/apache/DefaultApacheHttpClientBuilderTest.java b/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/http/apache/DefaultApacheHttpClientBuilderTest.java new file mode 100644 index 00000000..24a45eea --- /dev/null +++ b/weixin-java-common/src/test/java/me/chanjar/weixin/common/util/http/apache/DefaultApacheHttpClientBuilderTest.java @@ -0,0 +1,64 @@ +package me.chanjar.weixin.common.util.http.apache; + +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.testng.Assert; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class DefaultApacheHttpClientBuilderTest { + @Test + public void testBuild() throws Exception { + DefaultApacheHttpClientBuilder builder1 = DefaultApacheHttpClientBuilder.get(); + DefaultApacheHttpClientBuilder builder2 = DefaultApacheHttpClientBuilder.get(); + Assert.assertSame(builder1, builder2, "DefaultApacheHttpClientBuilder为单例,获取到的对象应该相同"); + List threadList = new ArrayList<>(10); + for (int i = 0; i < 10; i++) { + TestThread thread = new TestThread(); + thread.start(); + threadList.add(thread); + } + for (TestThread testThread : threadList) { + testThread.join(); + Assert.assertNotEquals(-1,testThread.getRespState(),"请求响应code不应为-1"); + } + + for (int i = 1; i < threadList.size(); i++) { + TestThread thread1 = threadList.get(i - 1); + TestThread thread2 = threadList.get(i); + Assert.assertSame( + thread1.getClient(), + thread2.getClient(), + "DefaultApacheHttpClientBuilder为单例,并持有了相同的HttpClient" + ); + } + } + + + public static class TestThread extends Thread { + private CloseableHttpClient client; + private int respState = -1; + + @Override + public void run() { + client = DefaultApacheHttpClientBuilder.get().build(); + HttpGet httpGet = new HttpGet("http://www.sina.com.cn/"); + try (CloseableHttpResponse resp = client.execute(httpGet)){ + respState = resp.getStatusLine().getStatusCode(); + } catch (IOException ignored) { + } + } + + public CloseableHttpClient getClient() { + return client; + } + + public int getRespState() { + return respState; + } + } +}