diff --git a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/DefaultApacheHttpClientBuilder.java b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/DefaultApacheHttpClientBuilder.java index cb4e571f..54bd5b68 100644 --- a/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/DefaultApacheHttpClientBuilder.java +++ b/weixin-java-common/src/main/java/me/chanjar/weixin/common/util/http/DefaultApacheHttpClientBuilder.java @@ -1,8 +1,6 @@ package me.chanjar.weixin.common.util.http; -import java.io.IOException; -import java.util.concurrent.TimeUnit; - +import me.chanjar.weixin.common.util.StringUtils; import org.apache.http.annotation.NotThreadSafe; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; @@ -22,15 +20,22 @@ 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.protocol.HttpContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; -import me.chanjar.weixin.common.util.StringUtils; +import java.io.IOException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; /** * httpclient 连接管理器 + * * @author kakotor */ @NotThreadSafe public class DefaultApacheHttpClientBuilder implements ApacheHttpClientBuilder { + protected final Logger log = LoggerFactory.getLogger(DefaultApacheHttpClientBuilder.class); + private final AtomicBoolean prepared = new AtomicBoolean(false); private int connectionRequestTimeout = 3000; private int connectionTimeout = 5000; private int soTimeout = 5000; @@ -47,21 +52,17 @@ public class DefaultApacheHttpClientBuilder implements ApacheHttpClientBuilder { }; private SSLConnectionSocketFactory sslConnectionSocketFactory = SSLConnectionSocketFactory.getSocketFactory(); private PlainConnectionSocketFactory plainConnectionSocketFactory = PlainConnectionSocketFactory.getSocketFactory(); - private String httpProxyHost; private int httpProxyPort; private String httpProxyUsername; private String httpProxyPassword; - /** * 闲置连接监控线程 */ private IdleConnectionMonitorThread idleConnectionMonitorThread; - private HttpClientBuilder httpClientBuilder; private DefaultApacheHttpClientBuilder() { - prepare(); } public static DefaultApacheHttpClientBuilder get() { @@ -98,11 +99,98 @@ public class DefaultApacheHttpClientBuilder implements ApacheHttpClientBuilder { return this; } + /** + * 获取链接的超时时间设置,默认3000ms + *

+ * 设置为零时不超时,一直等待. + * 设置为负数是使用系统默认设置(非上述的3000ms的默认值,而是httpclient的默认设置). + *

+ * + * @param connectionRequestTimeout 获取链接的超时时间设置(单位毫秒),默认3000ms + */ + public void setConnectionRequestTimeout(int connectionRequestTimeout) { + this.connectionRequestTimeout = connectionRequestTimeout; + } + + /** + * 建立链接的超时时间,默认为5000ms.由于是在链接池获取链接,此设置应该并不起什么作用 + *

+ * 设置为零时不超时,一直等待. + * 设置为负数是使用系统默认设置(非上述的5000ms的默认值,而是httpclient的默认设置). + *

+ * + * @param connectionTimeout 建立链接的超时时间设置(单位毫秒),默认5000ms + */ + public void setConnectionTimeout(int connectionTimeout) { + this.connectionTimeout = connectionTimeout; + } + + /** + * 默认NIO的socket超时设置,默认5000ms. + * + * @param soTimeout 默认NIO的socket超时设置,默认5000ms. + * @see java.net.SocketOptions#SO_TIMEOUT + */ + public void setSoTimeout(int soTimeout) { + this.soTimeout = soTimeout; + } + + /** + * 空闲链接的超时时间,默认60000ms. + *

+ * 超时的链接将在下一次空闲链接检查是被销毁 + *

+ * + * @param idleConnTimeout 空闲链接的超时时间,默认60000ms. + */ + public void setIdleConnTimeout(int idleConnTimeout) { + this.idleConnTimeout = idleConnTimeout; + } + + /** + * 检查空间链接的间隔周期,默认60000ms. + * + * @param checkWaitTime 检查空间链接的间隔周期,默认60000ms. + */ + public void setCheckWaitTime(int checkWaitTime) { + this.checkWaitTime = checkWaitTime; + } + + /** + * 每路的最大链接数,默认10 + * + * @param maxConnPerHost 每路的最大链接数,默认10 + */ + public void setMaxConnPerHost(int maxConnPerHost) { + this.maxConnPerHost = maxConnPerHost; + } + + /** + * 最大总连接数,默认50 + * + * @param maxTotalConn 最大总连接数,默认50 + */ + public void setMaxTotalConn(int maxTotalConn) { + this.maxTotalConn = maxTotalConn; + } + + /** + * 自定义httpclient的User Agent + * + * @param userAgent User Agent + */ + public void setUserAgent(String userAgent) { + this.userAgent = userAgent; + } + public IdleConnectionMonitorThread getIdleConnectionMonitorThread() { return this.idleConnectionMonitorThread; } - private void prepare() { + private synchronized void prepare() { + if(prepared.get()){ + return; + } Registry registry = RegistryBuilder.create() .register("http", this.plainConnectionSocketFactory) .register("https", this.sslConnectionSocketFactory) @@ -149,11 +237,14 @@ public class DefaultApacheHttpClientBuilder implements ApacheHttpClientBuilder { if (StringUtils.isNotBlank(this.userAgent)) { this.httpClientBuilder.setUserAgent(this.userAgent); } - + prepared.set(true); } @Override public CloseableHttpClient build() { + if(!prepared.get()){ + prepare(); + } return this.httpClientBuilder.build(); }