diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/client/HttpClientConfig.java b/hutool-http/src/main/java/org/dromara/hutool/http/client/HttpClientConfig.java new file mode 100644 index 000000000..9a16cf620 --- /dev/null +++ b/hutool-http/src/main/java/org/dromara/hutool/http/client/HttpClientConfig.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2024 Hutool Team and hutool.cn + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.dromara.hutool.http.client; + +/** + * 针对HttpClient5和HttpClient4的配置 + * + * @author Looly + * @since 6.0.0 + */ +public class HttpClientConfig extends ClientConfig { + + /** + * 创建新的 HttpClientConfig + * + * @return HttpClientConfig + */ + public static HttpClientConfig of() { + return new HttpClientConfig(); + } + + /** + * 最大连接数 + */ + private int maxTotal; + /** + * 每个路由的最大连接数 + */ + private int maxPerRoute; + + /** + * 获取最大连接总数 + * + * @return 最大连接总数 + */ + public int getMaxTotal() { + return maxTotal; + } + + /** + * 设置最大连接总数 + * + * @param maxTotal 最大连接总数 + * @return 当前HttpClientConfig实例,用于链式调用 + */ + public HttpClientConfig setMaxTotal(final int maxTotal) { + this.maxTotal = maxTotal; + return this; + } + + /** + * 获取每个路由的最大连接数 + * + * @return 每个路由的最大连接数 + */ + public int getMaxPerRoute() { + return maxPerRoute; + } + + /** + * 设置每个路由的最大连接数 + * + * @param maxPerRoute 每个路由的最大连接数 + * @return 当前HttpClientConfig实例,用于链式调用 + */ + public HttpClientConfig setMaxPerRoute(final int maxPerRoute) { + this.maxPerRoute = maxPerRoute; + return this; + } +} diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/ClientEngine.java b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/ClientEngine.java index bdf6a636b..f30a7325e 100644 --- a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/ClientEngine.java +++ b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/ClientEngine.java @@ -32,6 +32,14 @@ public interface ClientEngine extends Closeable { /** * 设置客户端引擎参数,如超时、代理等信息 + * 对不同引擎个性化配置,使用对应的{@link ClientConfig} 子类: + * + * + *

+ * 如果混用这些配置,则个性配置不生效 * * @param config 客户端设置 * @return this diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/ClientEngineFactory.java b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/ClientEngineFactory.java index f98bce56b..791bc0822 100644 --- a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/ClientEngineFactory.java +++ b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/ClientEngineFactory.java @@ -43,7 +43,15 @@ public class ClientEngineFactory { /** * 根据用户引入的HTTP客户端引擎jar,自动创建对应的HTTP客户端引擎对象
- * 推荐创建的引擎单例使用,此方法每次调用会返回新的引擎 + * 推荐创建的引擎单例使用,此方法每次调用会返回新的引擎
+ * 对不同引擎个性化配置,使用对应的{@link ClientConfig} 子类: + * + *

+ *

+ * 如果混用这些配置,则个性配置不生效 * * @param config Http客户端配置 * @return {@code ClientEngine} diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient4/HttpClient4Engine.java b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient4/HttpClient4Engine.java index 4903d523d..b17c2641b 100644 --- a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient4/HttpClient4Engine.java +++ b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient4/HttpClient4Engine.java @@ -29,6 +29,7 @@ import org.apache.http.impl.client.BasicCredentialsProvider; 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.dromara.hutool.core.io.IoUtil; import org.dromara.hutool.core.lang.Assert; @@ -37,6 +38,7 @@ import org.dromara.hutool.core.util.ObjUtil; import org.dromara.hutool.http.GlobalHeaders; import org.dromara.hutool.http.HttpException; import org.dromara.hutool.http.client.ClientConfig; +import org.dromara.hutool.http.client.HttpClientConfig; import org.dromara.hutool.http.client.Request; import org.dromara.hutool.http.client.Response; import org.dromara.hutool.http.client.body.HttpBody; @@ -110,7 +112,7 @@ public class HttpClient4Engine extends AbstractClientEngine { } final HttpClientBuilder clientBuilder = HttpClients.custom(); - final ClientConfig config = ObjUtil.defaultIfNull(this.config, ClientConfig::of); + final ClientConfig config = ObjUtil.defaultIfNull(this.config, HttpClientConfig::of); // SSL配置 final SSLInfo sslInfo = config.getSslInfo(); if (null != sslInfo) { @@ -120,6 +122,7 @@ public class HttpClient4Engine extends AbstractClientEngine { clientBuilder.disableAuthCaching(); } + clientBuilder.setConnectionManager(buildConnectionManager(config)); clientBuilder.setDefaultRequestConfig(buildRequestConfig(config)); // 设置默认头信息 @@ -189,6 +192,24 @@ public class HttpClient4Engine extends AbstractClientEngine { sslInfo.getHostnameVerifier()); } + /** + * 构建连接池管理器 + * @param config 配置 + * @return PoolingHttpClientConnectionManager + */ + private PoolingHttpClientConnectionManager buildConnectionManager(final ClientConfig config) { + final PoolingHttpClientConnectionManager manager = new PoolingHttpClientConnectionManager(); + + // 连接池配置 + if(config instanceof HttpClientConfig){ + final HttpClientConfig httpClientConfig = (HttpClientConfig) config; + manager.setMaxTotal(httpClientConfig.getMaxTotal()); + manager.setDefaultMaxPerRoute(httpClientConfig.getMaxPerRoute()); + } + + return manager; + } + /** * 构建请求配置,包括连接请求超时和响应(读取)超时 * diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient5/HttpClient5Engine.java b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient5/HttpClient5Engine.java index 129a8ea67..62b0b62ba 100644 --- a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient5/HttpClient5Engine.java +++ b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/httpclient5/HttpClient5Engine.java @@ -40,6 +40,7 @@ import org.dromara.hutool.core.util.ObjUtil; import org.dromara.hutool.http.GlobalHeaders; import org.dromara.hutool.http.HttpException; import org.dromara.hutool.http.client.ClientConfig; +import org.dromara.hutool.http.client.HttpClientConfig; import org.dromara.hutool.http.client.Request; import org.dromara.hutool.http.client.Response; import org.dromara.hutool.http.client.body.HttpBody; @@ -115,7 +116,7 @@ public class HttpClient5Engine extends AbstractClientEngine { final HttpClientBuilder clientBuilder = HttpClients.custom(); - final ClientConfig config = ObjUtil.defaultIfNull(this.config, ClientConfig::of); + final ClientConfig config = ObjUtil.defaultIfNull(this.config, HttpClientConfig::of); clientBuilder.setConnectionManager(buildConnectionManager(config)); clientBuilder.setDefaultRequestConfig(buildRequestConfig(config)); if(config.isDisableCache()){ @@ -200,6 +201,19 @@ public class HttpClient5Engine extends AbstractClientEngine { .setConnectTimeout(connectionTimeout, TimeUnit.MILLISECONDS).build()); } + // 连接池配置 + if(config instanceof HttpClientConfig){ + final HttpClientConfig httpClientConfig = (HttpClientConfig) config; + final int maxTotal = httpClientConfig.getMaxTotal(); + final int maxPerRoute = httpClientConfig.getMaxPerRoute(); + if (maxTotal > 0) { + connectionManagerBuilder.setMaxConnTotal(maxTotal); + } + if (maxPerRoute > 0) { + connectionManagerBuilder.setMaxConnPerRoute(maxPerRoute); + } + } + return connectionManagerBuilder.build(); } diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/okhttp/OkHttpClientConfig.java b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/okhttp/OkHttpClientConfig.java new file mode 100644 index 000000000..f2fb5dc2f --- /dev/null +++ b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/okhttp/OkHttpClientConfig.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2024 Hutool Team and hutool.cn + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.dromara.hutool.http.client.engine.okhttp; + +import okhttp3.ConnectionPool; +import org.dromara.hutool.http.client.ClientConfig; + +/** + * OkHttpClient 配置 + * + * @author Looly + * @since 6.0.0 + */ +public class OkHttpClientConfig extends ClientConfig { + /** + * 创建新的 OkHttpClientConfig + * + * @return OkHttpClientConfig + */ + public static OkHttpClientConfig of() { + return new OkHttpClientConfig(); + } + + private ConnectionPool connectionPool; + + /** + * 获取连接池 + * + * @return ConnectionPool + */ + public ConnectionPool getConnectionPool() { + return connectionPool; + } + + /** + * 设置连接池 + * + * @param connectionPool ConnectionPool + * @return this + */ + public OkHttpClientConfig setConnectionPool(final ConnectionPool connectionPool) { + this.connectionPool = connectionPool; + return this; + } +} diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/okhttp/OkHttpEngine.java b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/okhttp/OkHttpEngine.java index fc57cd65d..bb803fea0 100644 --- a/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/okhttp/OkHttpEngine.java +++ b/hutool-http/src/main/java/org/dromara/hutool/http/client/engine/okhttp/OkHttpEngine.java @@ -97,22 +97,27 @@ public class OkHttpEngine extends AbstractClientEngine { final OkHttpClient.Builder builder = new OkHttpClient.Builder(); - final ClientConfig conf = ObjUtil.defaultIfNull(this.config, ClientConfig::of); + final ClientConfig config = ObjUtil.defaultIfNull(this.config, ClientConfig::of); // 连接超时 - final int connectionTimeout = conf.getConnectionTimeout(); + final int connectionTimeout = config.getConnectionTimeout(); if (connectionTimeout > 0) { builder.connectTimeout(connectionTimeout, TimeUnit.MILLISECONDS); } // 读写超时 - final int readTimeout = conf.getReadTimeout(); + final int readTimeout = config.getReadTimeout(); if (readTimeout > 0) { // 读写共用读取超时 - builder.readTimeout(conf.getReadTimeout(), TimeUnit.MILLISECONDS) - .writeTimeout(conf.getReadTimeout(), TimeUnit.MILLISECONDS); + builder.readTimeout(config.getReadTimeout(), TimeUnit.MILLISECONDS) + .writeTimeout(config.getReadTimeout(), TimeUnit.MILLISECONDS); + } + + // 连接池 + if(config instanceof OkHttpClientConfig){ + builder.connectionPool(((OkHttpClientConfig) config).getConnectionPool()); } // SSL - final SSLInfo sslInfo = conf.getSslInfo(); + final SSLInfo sslInfo = config.getSslInfo(); if (null != sslInfo){ final SSLSocketFactory socketFactory = sslInfo.getSocketFactory(); final X509TrustManager trustManager = sslInfo.getTrustManager(); @@ -122,7 +127,7 @@ public class OkHttpEngine extends AbstractClientEngine { } // 设置代理 - setProxy(builder, conf); + setProxy(builder, config); // 默认关闭自动跳转 builder.followRedirects(false);