JAVA - HttpClient(JDK11)
Posted 任某某
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA - HttpClient(JDK11)相关的知识,希望对你有一定的参考价值。
1 HttpClient简介
以可扩展的面向对象的结构实现了HTTP全部的方法(GET、POST、put、delete、head、options、trace)
支持HTTPS协议
通过HTTP代理建立透明的连接
连接管理器支持多线程应用。支持设置最大连接数,同时支持设置每个主机的最大连接数,发现并关闭过期的连接
自动处理Set-Cookie中的Cookie
插件式的自定义Cookie策略
request的输出流可以避免流中内容直接缓冲到socket服务器
Response的输入流可以有效的从socket服务器直接读取相应内容
// 同步 示例
HttpClient client = HttpClient.newBuilder()
.version(Version.HTTP_1_1)
.followRedirects(Redirect.NORMAL)
.connectTimeout(Duration.ofSeconds(20))
.proxy(ProxySelector
.of(new InetSocketAddress("proxy.example.com", 80)))
.authenticator(Authenticator.getDefault())
.build();
HttpResponse<String> response = client.send(request, BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());
// 异步 示例
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://foo.com/"))
.timeout(Duration.ofMinutes(2))
.header("Content-Type", "application/json")
.POST(BodyPublishers.ofFile(Paths.get("file.json")))
.build();
client.sendAsync(request, BodyHandlers.ofString())
.thenApply(HttpResponse::body)
.thenAccept(System.out::println);
2 创建HttpClient
//创建 builder
HttpClient.Builder builder = HttpClient.newBuilder();
//链式调用
HttpClient client = builder
//http 协议版本 1.1 或者 2
.version(HttpClient.Version.HTTP_2) //.version(HttpClient.Version.HTTP_1_1)
//连接超时时间,单位为毫秒
.connectTimeout(Duration.ofMillis(5000)) //.connectTimeout(Duration.ofMinutes(1))
//连接完成之后的转发策略
.followRedirects(HttpClient.Redirect.NEVER) //.followRedirects(HttpClient.Redirect.ALWAYS)
//指定线程池
.executor(Executors.newFixedThreadPool(5))
//认证,默认情况下 Authenticator.getDefault() 是 null 值,会报错
//.authenticator(Authenticator.getDefault())
//代理地址
//.proxy(ProxySelector.of(new InetSocketAddress("http://www.baidu.com", 8080)))
//缓存,默认情况下 CookieHandler.getDefault() 是 null 值,会报错
//.cookieHandler(CookieHandler.getDefault())
//创建完成
.build();
public HttpClient build() {
return HttpClientImpl.create(this);
}
HttpClientImpl impl = new HttpClientImpl(builder, facadeFactory);
private HttpClientImpl(HttpClientBuilderImpl builder,
SingleFacadeFactory facadeFactory) {
//CLIENT_IDS 是 AtomicLong 类型的变量,使用 incrementAndGet() 方法实现自增长的 id
id = CLIENT_IDS.incrementAndGet();
//记录下存有 id 的字符串
dbgTag = "HttpClientImpl(" + id +")";
//ssl 认证
if (builder.sslContext == null) {
try {
sslContext = SSLContext.getDefault();
} catch (NoSuchAlgorithmException ex) {
throw new InternalError(ex);
}
} else {
sslContext = builder.sslContext;
}
//线程池,没有的话就默认创建一个
Executor ex = builder.executor;
if (ex == null) {
ex = Executors.newCachedThreadPool(new DefaultThreadFactory(id));
isDefaultExecutor = true;
} else {
isDefaultExecutor = false;
}
delegatingExecutor = new DelegatingExecutor(this::isSelectorThread, ex);
facadeRef = new WeakReference<>(facadeFactory.createFacade(this));
//处理 http 2 的 client 类
client2 = new Http2ClientImpl(this);
//缓存
cookieHandler = builder.cookieHandler;
//超时时间
connectTimeout = builder.connectTimeout;
//转发策略,默认为 NEVER
followRedirects = builder.followRedirects == null ?
Redirect.NEVER : builder.followRedirects;
//代理设置
this.userProxySelector = Optional.ofNullable(builder.proxy);
this.proxySelector = userProxySelector
.orElseGet(HttpClientImpl::getDefaultProxySelector);
if (debug.on())
debug.log("proxySelector is %s (user-supplied=%s)",
this.proxySelector, userProxySelector.isPresent());
//认证设置
authenticator = builder.authenticator;
//设置 http 协议版本
if (builder.version == null) {
version = HttpClient.Version.HTTP_2;
} else {
version = builder.version;
}
if (builder.sslParams == null) {
sslParams = getDefaultParams(sslContext);
} else {
sslParams = builder.sslParams;
}
//连接线程池
connections = new ConnectionPool(id);
connections.start();
timeouts = new TreeSet<>();
//SelectorManager 本质上是 Thread 类的封装
//selmgr 会开启一条线程,HttpClient 的主要逻辑运行在此线程中
//所以说 HttpClient 是非阻塞的,因为并不跑在主线程中
try {
selmgr = new SelectorManager(this);
} catch (IOException e) {
// unlikely
throw new InternalError(e);
}
//设置为守护线程
selmgr.setDaemon(true);
filters = new FilterFactory();
initFilters();
assert facadeRef.get() != null;
}
3 HttpRequst是请求的主体部分
//创建 builder
HttpRequest.Builder reBuilder = HttpRequest.newBuilder();
//链式调用
HttpRequest request = reBuilder
//存入消息头
//消息头是保存在一张 TreeMap 里的
.header("Content-Type", "application/json")
//http 协议版本
.version(HttpClient.Version.HTTP_2)
//url 地址
.uri(URI.create("http://openjdk.java.net/"))
//超时时间
.timeout(Duration.ofMillis(5009))
//发起一个 post 消息,需要存入一个消息体
//.POST(HttpRequest.BodyPublishers.ofString("hello"))
//发起一个 get 消息,get 不需要消息体
.GET()
//method(...) 方法是 POST(...) 和 GET(...) 方法的底层,效果一样
//.method("POST",HttpRequest.BodyPublishers.ofString("hello"))
//创建完成
.build();
4 发送请求 HttpResponse
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
String appKeySys = DingTalkConfig.APP_KEY;
String appSecretSys = DingTalkConfig.APP_SECRET;
//钉钉请求
// DefaultDingTalkClient client = new DefaultDingTalkClient(Constant.DingTalkConfig.URL_GET_TOKKEN);
// OapiGettokenRequest request = new OapiGettokenRequest();
HttpClient.Builder builder = HttpClient.newBuilder();
HttpClient client = builder.version(HttpClient.Version.HTTP_2).connectTimeout(Duration.ofMillis(5000))
.followRedirects(HttpClient.Redirect.ALWAYS)
.build();
HttpRequest.Builder reBuilder = HttpRequest.newBuilder();
Map<String,Object> dingKeyMap = jdbcTemplate.queryForMap("select CORP_ID,SECRET from xgtz_data_factory.wechat_access_token where id = 2");
if (!StringUtils.isEmpty(dingKeyMap)){
if (!StringUtils.isEmpty(dingKeyMap.get("CORP_ID")) && !StringUtils.isEmpty(dingKeyMap.get("SECRET"))){
appKeySys = TypeUtils.castToString(dingKeyMap.get("CORP_ID"));
appSecretSys = TypeUtils.castToString(dingKeyMap.get("SECRET"));
}
}
// request.setAppkey(appKeySys);
// request.setAppsecret(appSecretSys);
// request.setHttpMethod("GET");
// OapiGettokenResponse response = client.execute(request);
HttpRequest request = reBuilder.header("Content-Type", "application/json")
.GET()
.timeout(Duration.ofMillis(6000))
.uri(URI.create(
Constant.DingTalkConfig.URL_GET_TOKKEN
.concat("?appkey=").concat(appKeySys)
.concat("&appsecret=").concat(appSecretSys)
))
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
end
下一篇记录下RestTemplate
每天积累一点点,十天头顶秃一片,淦
以上是关于JAVA - HttpClient(JDK11)的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Java JDK HttpClient 中使用 socks 代理