add Config

This commit is contained in:
Looly 2024-09-05 20:16:48 +08:00
parent 06c0544c11
commit 6ae4169951
7 changed files with 209 additions and 10 deletions

View File

@ -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;
}
}

View File

@ -32,6 +32,14 @@ public interface ClientEngine extends Closeable {
/** /**
* 设置客户端引擎参数如超时代理等信息 * 设置客户端引擎参数如超时代理等信息
* 对不同引擎个性化配置使用对应的{@link ClientConfig} 子类
*
* <ul>
* <li>HttpClient4和HttpClient5使用{@link org.dromara.hutool.http.client.HttpClientConfig}</li>
* <li>OkHttp使用{@link org.dromara.hutool.http.client.engine.okhttp.OkHttpClientConfig}</li>
* </ul>
* <p>
* 如果混用这些配置则个性配置不生效
* *
* @param config 客户端设置 * @param config 客户端设置
* @return this * @return this

View File

@ -43,7 +43,15 @@ public class ClientEngineFactory {
/** /**
* 根据用户引入的HTTP客户端引擎jar自动创建对应的HTTP客户端引擎对象<br> * 根据用户引入的HTTP客户端引擎jar自动创建对应的HTTP客户端引擎对象<br>
* 推荐创建的引擎单例使用此方法每次调用会返回新的引擎 * 推荐创建的引擎单例使用此方法每次调用会返回新的引擎<br>
* 对不同引擎个性化配置使用对应的{@link ClientConfig} 子类
*
* <ul>
* <li>HttpClient4和HttpClient5使用{@link org.dromara.hutool.http.client.HttpClientConfig}</li>
* <li>OkHttp使用{@link org.dromara.hutool.http.client.engine.okhttp.OkHttpClientConfig}</li>
* </ul>
* <p>
* 如果混用这些配置则个性配置不生效
* *
* @param config Http客户端配置 * @param config Http客户端配置
* @return {@code ClientEngine} * @return {@code ClientEngine}

View File

@ -29,6 +29,7 @@ import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients; import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader; import org.apache.http.message.BasicHeader;
import org.dromara.hutool.core.io.IoUtil; import org.dromara.hutool.core.io.IoUtil;
import org.dromara.hutool.core.lang.Assert; 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.GlobalHeaders;
import org.dromara.hutool.http.HttpException; import org.dromara.hutool.http.HttpException;
import org.dromara.hutool.http.client.ClientConfig; 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.Request;
import org.dromara.hutool.http.client.Response; import org.dromara.hutool.http.client.Response;
import org.dromara.hutool.http.client.body.HttpBody; import org.dromara.hutool.http.client.body.HttpBody;
@ -110,7 +112,7 @@ public class HttpClient4Engine extends AbstractClientEngine {
} }
final HttpClientBuilder clientBuilder = HttpClients.custom(); final HttpClientBuilder clientBuilder = HttpClients.custom();
final ClientConfig config = ObjUtil.defaultIfNull(this.config, ClientConfig::of); final ClientConfig config = ObjUtil.defaultIfNull(this.config, HttpClientConfig::of);
// SSL配置 // SSL配置
final SSLInfo sslInfo = config.getSslInfo(); final SSLInfo sslInfo = config.getSslInfo();
if (null != sslInfo) { if (null != sslInfo) {
@ -120,6 +122,7 @@ public class HttpClient4Engine extends AbstractClientEngine {
clientBuilder.disableAuthCaching(); clientBuilder.disableAuthCaching();
} }
clientBuilder.setConnectionManager(buildConnectionManager(config));
clientBuilder.setDefaultRequestConfig(buildRequestConfig(config)); clientBuilder.setDefaultRequestConfig(buildRequestConfig(config));
// 设置默认头信息 // 设置默认头信息
@ -189,6 +192,24 @@ public class HttpClient4Engine extends AbstractClientEngine {
sslInfo.getHostnameVerifier()); 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;
}
/** /**
* 构建请求配置包括连接请求超时和响应读取超时 * 构建请求配置包括连接请求超时和响应读取超时
* *

View File

@ -40,6 +40,7 @@ import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.http.GlobalHeaders; import org.dromara.hutool.http.GlobalHeaders;
import org.dromara.hutool.http.HttpException; import org.dromara.hutool.http.HttpException;
import org.dromara.hutool.http.client.ClientConfig; 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.Request;
import org.dromara.hutool.http.client.Response; import org.dromara.hutool.http.client.Response;
import org.dromara.hutool.http.client.body.HttpBody; import org.dromara.hutool.http.client.body.HttpBody;
@ -115,7 +116,7 @@ public class HttpClient5Engine extends AbstractClientEngine {
final HttpClientBuilder clientBuilder = HttpClients.custom(); 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.setConnectionManager(buildConnectionManager(config));
clientBuilder.setDefaultRequestConfig(buildRequestConfig(config)); clientBuilder.setDefaultRequestConfig(buildRequestConfig(config));
if(config.isDisableCache()){ if(config.isDisableCache()){
@ -200,6 +201,19 @@ public class HttpClient5Engine extends AbstractClientEngine {
.setConnectTimeout(connectionTimeout, TimeUnit.MILLISECONDS).build()); .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(); return connectionManagerBuilder.build();
} }

View File

@ -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;
}
}

View File

@ -97,22 +97,27 @@ public class OkHttpEngine extends AbstractClientEngine {
final OkHttpClient.Builder builder = new OkHttpClient.Builder(); 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) { if (connectionTimeout > 0) {
builder.connectTimeout(connectionTimeout, TimeUnit.MILLISECONDS); builder.connectTimeout(connectionTimeout, TimeUnit.MILLISECONDS);
} }
// 读写超时 // 读写超时
final int readTimeout = conf.getReadTimeout(); final int readTimeout = config.getReadTimeout();
if (readTimeout > 0) { if (readTimeout > 0) {
// 读写共用读取超时 // 读写共用读取超时
builder.readTimeout(conf.getReadTimeout(), TimeUnit.MILLISECONDS) builder.readTimeout(config.getReadTimeout(), TimeUnit.MILLISECONDS)
.writeTimeout(conf.getReadTimeout(), TimeUnit.MILLISECONDS); .writeTimeout(config.getReadTimeout(), TimeUnit.MILLISECONDS);
}
// 连接池
if(config instanceof OkHttpClientConfig){
builder.connectionPool(((OkHttpClientConfig) config).getConnectionPool());
} }
// SSL // SSL
final SSLInfo sslInfo = conf.getSslInfo(); final SSLInfo sslInfo = config.getSslInfo();
if (null != sslInfo){ if (null != sslInfo){
final SSLSocketFactory socketFactory = sslInfo.getSocketFactory(); final SSLSocketFactory socketFactory = sslInfo.getSocketFactory();
final X509TrustManager trustManager = sslInfo.getTrustManager(); final X509TrustManager trustManager = sslInfo.getTrustManager();
@ -122,7 +127,7 @@ public class OkHttpEngine extends AbstractClientEngine {
} }
// 设置代理 // 设置代理
setProxy(builder, conf); setProxy(builder, config);
// 默认关闭自动跳转 // 默认关闭自动跳转
builder.followRedirects(false); builder.followRedirects(false);