mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-12-08 10:09:06 +08:00
add jdk11+ HttpClient support
This commit is contained in:
parent
10d660fb06
commit
ef6fc50fbb
@ -29,7 +29,7 @@ public class SimpleWrapper<T> implements Wrapper<T> {
|
|||||||
/**
|
/**
|
||||||
* 原始对象
|
* 原始对象
|
||||||
*/
|
*/
|
||||||
protected final T raw;
|
protected T raw;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造
|
* 构造
|
||||||
|
|||||||
@ -66,7 +66,7 @@ public class ClientEngineFactory {
|
|||||||
/**
|
/**
|
||||||
* 创建自定义引擎
|
* 创建自定义引擎
|
||||||
*
|
*
|
||||||
* @param engineName 引擎名称,忽略大小写,如`HttpClient4`、`HttpClient5`、`OkHttp`、`JdkClient`
|
* @param engineName 引擎名称,忽略大小写,如`HttpClient4`、`HttpClient5`、`OkHttp`、`JdkClient`、`Jdk11Client`
|
||||||
* @return 引擎
|
* @return 引擎
|
||||||
* @throws HttpException 无对应名称的引擎
|
* @throws HttpException 无对应名称的引擎
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -24,6 +24,8 @@ import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
|||||||
import cn.hutool.v7.core.lang.builder.Builder;
|
import cn.hutool.v7.core.lang.builder.Builder;
|
||||||
import cn.hutool.v7.http.ssl.SSLInfo;
|
import cn.hutool.v7.http.ssl.SSLInfo;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HttpClient4连接工厂注册器构建器
|
* HttpClient4连接工厂注册器构建器
|
||||||
*
|
*
|
||||||
@ -31,6 +33,7 @@ import cn.hutool.v7.http.ssl.SSLInfo;
|
|||||||
* @since 6.0.0
|
* @since 6.0.0
|
||||||
*/
|
*/
|
||||||
public class ConnectionSocketFactoryRegistryBuilder implements Builder<Registry<ConnectionSocketFactory>> {
|
public class ConnectionSocketFactoryRegistryBuilder implements Builder<Registry<ConnectionSocketFactory>> {
|
||||||
|
@Serial
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -0,0 +1,126 @@
|
|||||||
|
package cn.hutool.v7.http.client.engine.jdk11;
|
||||||
|
|
||||||
|
import cn.hutool.v7.http.HttpException;
|
||||||
|
import cn.hutool.v7.http.client.ClientConfig;
|
||||||
|
import cn.hutool.v7.http.client.Request;
|
||||||
|
import cn.hutool.v7.http.client.Response;
|
||||||
|
import cn.hutool.v7.http.client.cookie.InMemoryCookieStore;
|
||||||
|
import cn.hutool.v7.http.client.engine.AbstractClientEngine;
|
||||||
|
import cn.hutool.v7.http.client.engine.jdk.JdkCookieManager;
|
||||||
|
import cn.hutool.v7.http.proxy.ProxyInfo;
|
||||||
|
import cn.hutool.v7.http.ssl.SSLInfo;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.ProxySelector;
|
||||||
|
import java.net.http.HttpClient;
|
||||||
|
import java.net.http.HttpRequest;
|
||||||
|
import java.net.http.HttpResponse;
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JDK11 HttpClient引擎实现
|
||||||
|
*
|
||||||
|
* @author looly
|
||||||
|
* @since 7.0.0
|
||||||
|
*/
|
||||||
|
public class Jdk11ClientEngine extends AbstractClientEngine {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HttpClient
|
||||||
|
*/
|
||||||
|
private HttpClient client;
|
||||||
|
/**
|
||||||
|
* Cookie管理
|
||||||
|
*/
|
||||||
|
private JdkCookieManager cookieManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取Cookie管理器
|
||||||
|
*
|
||||||
|
* @return Cookie管理器
|
||||||
|
*/
|
||||||
|
public JdkCookieManager getCookieManager() {
|
||||||
|
return this.cookieManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response send(final Request message) {
|
||||||
|
initEngine();
|
||||||
|
|
||||||
|
final HttpRequest.Builder builder = HttpRequest.newBuilder()
|
||||||
|
.uri(message.url().toURI())
|
||||||
|
.method(message.method().name(), null == message.body() ?
|
||||||
|
HttpRequest.BodyPublishers.noBody() :
|
||||||
|
HttpRequest.BodyPublishers.ofInputStream(message::bodyStream));
|
||||||
|
|
||||||
|
// Read超时
|
||||||
|
if(null != this.config){
|
||||||
|
builder.timeout(Duration.ofMillis(this.config.getReadTimeout()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自定义Headers
|
||||||
|
message.headers().forEach((k, v1) -> v1.forEach(v2 -> builder.header(k, v2)));
|
||||||
|
|
||||||
|
final HttpResponse<InputStream> response;
|
||||||
|
try {
|
||||||
|
response = this.client.send(builder.build(), HttpResponse.BodyHandlers.ofInputStream());
|
||||||
|
} catch (final Exception e) {
|
||||||
|
throw new HttpException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Jdk11HttpResponse(response, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getRawEngine() {
|
||||||
|
return this.client;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
// 关闭Cookie管理器
|
||||||
|
this.cookieManager = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void reset() {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initEngine() {
|
||||||
|
if (null != this.client) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final HttpClient.Builder builder = HttpClient.newBuilder()
|
||||||
|
.version(HttpClient.Version.HTTP_1_1);
|
||||||
|
|
||||||
|
final ClientConfig config = this.config;
|
||||||
|
if(null != config){
|
||||||
|
builder.connectTimeout(Duration.ofMillis(config.getConnectionTimeout()));
|
||||||
|
|
||||||
|
// SSL
|
||||||
|
final SSLInfo sslInfo = config.getSslInfo();
|
||||||
|
if(null != sslInfo){
|
||||||
|
builder.sslContext(sslInfo.getSslContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cookie
|
||||||
|
if (config.isUseCookieManager()) {
|
||||||
|
this.cookieStore = new InMemoryCookieStore();
|
||||||
|
this.cookieManager = new JdkCookieManager(this.cookieStore);
|
||||||
|
builder.cookieHandler(this.cookieManager.getCookieManager());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proxy
|
||||||
|
final ProxyInfo proxy = config.getProxy();
|
||||||
|
if (null != proxy) {
|
||||||
|
builder.proxy(proxy.getProxySelector());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.client = builder.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,87 @@
|
|||||||
|
package cn.hutool.v7.http.client.engine.jdk11;
|
||||||
|
|
||||||
|
import cn.hutool.v7.core.lang.wrapper.SimpleWrapper;
|
||||||
|
import cn.hutool.v7.http.GlobalCompressStreamRegister;
|
||||||
|
import cn.hutool.v7.http.HttpUtil;
|
||||||
|
import cn.hutool.v7.http.client.Request;
|
||||||
|
import cn.hutool.v7.http.client.Response;
|
||||||
|
import cn.hutool.v7.http.client.body.ResponseBody;
|
||||||
|
import cn.hutool.v7.http.meta.HeaderName;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.http.HttpResponse;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JDK11 Http响应包装类
|
||||||
|
*
|
||||||
|
* @author looly
|
||||||
|
* @since 7.0.0
|
||||||
|
*/
|
||||||
|
public class Jdk11HttpResponse extends SimpleWrapper<HttpResponse<InputStream>> implements Response {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 响应头
|
||||||
|
*/
|
||||||
|
private final Map<String, List<String>> headers;
|
||||||
|
/**
|
||||||
|
* 响应内容体,{@code null} 表示无内容
|
||||||
|
*/
|
||||||
|
private final ResponseBody body;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param rawRes 原始响应
|
||||||
|
* @param message 请求信息
|
||||||
|
*/
|
||||||
|
public Jdk11HttpResponse(final HttpResponse<InputStream> rawRes, final Request message) {
|
||||||
|
super(rawRes);
|
||||||
|
this.headers = this.raw.headers().map();
|
||||||
|
this.body = message.method().isIgnoreBody() ? null : new ResponseBody(this, bodyStream());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getStatus() {
|
||||||
|
return this.raw.statusCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String header(final String name) {
|
||||||
|
return HttpUtil.header(this.headers, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, List<String>> headers() {
|
||||||
|
return this.headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream bodyStream() {
|
||||||
|
// 直接取得解压后的原始流
|
||||||
|
return GlobalCompressStreamRegister.INSTANCE.wrapStream(this.raw.body(),
|
||||||
|
header(HeaderName.CONTENT_ENCODING.getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Response sync() {
|
||||||
|
final ResponseBody body = this.body;
|
||||||
|
if(null != body){
|
||||||
|
body.sync();
|
||||||
|
}
|
||||||
|
this.raw = null;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ResponseBody body() {
|
||||||
|
return this.body;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2025 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 基于JDK17+的HttpClient 封装的HTTP客户端
|
||||||
|
*
|
||||||
|
* @author Looly
|
||||||
|
* @since 7.0.0
|
||||||
|
*/
|
||||||
|
package cn.hutool.v7.http.client.engine.jdk11;
|
||||||
@ -78,10 +78,6 @@ public class OkHttpResponse implements Response {
|
|||||||
@Override
|
@Override
|
||||||
public InputStream bodyStream() {
|
public InputStream bodyStream() {
|
||||||
final okhttp3.ResponseBody body = rawRes.body();
|
final okhttp3.ResponseBody body = rawRes.body();
|
||||||
if(null == body){
|
|
||||||
return EmptyInputStream.INSTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return GlobalCompressStreamRegister.INSTANCE.wrapStream(body.byteStream(),
|
return GlobalCompressStreamRegister.INSTANCE.wrapStream(body.byteStream(),
|
||||||
this.rawRes.header(HeaderName.CONTENT_ENCODING.getValue()));
|
this.rawRes.header(HeaderName.CONTENT_ENCODING.getValue()));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,3 +18,4 @@ cn.hutool.v7.http.client.engine.httpclient5.HttpClient5Engine
|
|||||||
cn.hutool.v7.http.client.engine.httpclient4.HttpClient4Engine
|
cn.hutool.v7.http.client.engine.httpclient4.HttpClient4Engine
|
||||||
cn.hutool.v7.http.client.engine.okhttp.OkHttpEngine
|
cn.hutool.v7.http.client.engine.okhttp.OkHttpEngine
|
||||||
cn.hutool.v7.http.client.engine.jdk.JdkClientEngine
|
cn.hutool.v7.http.client.engine.jdk.JdkClientEngine
|
||||||
|
cn.hutool.v7.http.client.engine.jdk11.Jdk11ClientEngine
|
||||||
|
|||||||
@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2025 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 cn.hutool.v7.http.client;
|
||||||
|
|
||||||
|
import cn.hutool.v7.core.lang.Console;
|
||||||
|
import cn.hutool.v7.http.HttpUtil;
|
||||||
|
import cn.hutool.v7.http.client.engine.ClientEngine;
|
||||||
|
import cn.hutool.v7.http.meta.Method;
|
||||||
|
import org.junit.jupiter.api.Disabled;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class Jdk11HttpClientEngineTest {
|
||||||
|
|
||||||
|
@SuppressWarnings("resource")
|
||||||
|
@Test
|
||||||
|
@Disabled
|
||||||
|
public void getTest() {
|
||||||
|
final ClientEngine engine = HttpUtil.createClient("jdk11Client");
|
||||||
|
|
||||||
|
final Request req = Request.of("https://www.hutool.cn/").method(Method.GET);
|
||||||
|
final Response res = engine.send(req);
|
||||||
|
|
||||||
|
Console.log(res.getStatus());
|
||||||
|
Console.log(res.bodyStr());
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user