java.net.http.HttpClient使用示例解析
java自帶HttpClient使用
在使用java自帶的HttpClient時(shí), 發(fā)現(xiàn)一個(gè)現(xiàn)象,即有些以前常用http的header, 是不能夠set到請(qǐng)求里進(jìn)行傳遞的,在jdk.internal.net.http.common.Utils類中,可以看到
private static Set<String> getDisallowedHeaders() {
Set<String> headers = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
headers.addAll(Set.of("connection", "content-length", "expect", "host", "upgrade"));
String v = getNetProperty("jdk.httpclient.allowRestrictedHeaders");
if (v != null) {
// any headers found are removed from set.
String[] tokens = v.trim().split(",");
for (String token : tokens) {
headers.remove(token);
}
return Collections.unmodifiableSet(headers);
} else {
return Collections.unmodifiableSet(headers);
}
}connection, content-length, expect, host, upgrade這幾個(gè), 屬于禁止設(shè)置的。
校驗(yàn)
因?yàn)樵趈dk.internal.net.http.HttpRequestBuilderImpl中, 會(huì)進(jìn)行嚴(yán)格的校驗(yàn)
private void checkNameAndValue(String name, String value) {
requireNonNull(name, "name");
requireNonNull(value, "value");
if (!isValidName(name)) {
throw newIAE("invalid header name: \"%s\"", name);
}
if (!Utils.ALLOWED_HEADERS.test(name, null)) {
throw newIAE("restricted header name: \"%s\"", name);
}
if (!isValidValue(value)) {
throw newIAE("invalid header value: \"%s\"", value);
}
}控制連接復(fù)用
它自己控制連接的復(fù)用,所以設(shè)置不了connection這個(gè)header.從jdk.internal.net.http.ConnectionPool中可以看出一些參數(shù)
static final long KEEP_ALIVE = Utils.getIntegerNetProperty(
"jdk.httpclient.keepalive.timeout", 1200); // seconds
static final long MAX_POOL_SIZE = Utils.getIntegerNetProperty(
"jdk.httpclient.connectionPoolSize", 0); // unboundedjdk.internal.net.http.HttpConnection
從jdk.internal.net.http.HttpConnection中可以看到連接如何放入池中
/**
* Forces a call to the native implementation of the
* connection's channel to verify that this channel is still
* open.
* <p>
* This method should only be called just after an HTTP/1.1
* connection is retrieved from the HTTP/1.1 connection pool.
* It is used to trigger an early detection of the channel state,
* before handling the connection over to the HTTP stack.
* It helps minimizing race conditions where the selector manager
* thread hasn't woken up - or hasn't raised the event, before
* the connection was retrieved from the pool. It helps reduce
* the occurrence of "HTTP/1.1 parser received no bytes"
* exception, when the server closes the connection while
* it's being taken out of the pool.
* <p>
* This method attempts to read one byte from the underlying
* channel. Because the connection was in the pool - there
* should be nothing to read.
* <p>
* If {@code read} manages to read a byte off the connection, this is a
* protocol error: the method closes the connection and returns false.
* If {@code read} returns EOF, the method closes the connection and
* returns false.
* If {@code read} throws an exception, the method returns false.
* Otherwise, {@code read} returns 0, the channel appears to be
* still open, and the method returns true.
* @return true if the channel appears to be still open.
*/
final boolean checkOpen() {
if (isOpen()) {
try {
// channel is non blocking
int read = channel().read(ByteBuffer.allocate(1));
if (read == 0) return true;
close();
} catch (IOException x) {
debug.log("Pooled connection is no longer operational: %s",
x.toString());
return false;
}
}
return false;
}void closeOrReturnToCache(HttpHeaders hdrs) {
if (hdrs == null) {
// the connection was closed by server, eof
Log.logTrace("Cannot return connection to pool: closing {0}", this);
close();
return;
}
HttpClientImpl client = client();
if (client == null) {
Log.logTrace("Client released: closing {0}", this);
close();
return;
}
ConnectionPool pool = client.connectionPool();
boolean keepAlive = hdrs.firstValue("Connection")
.map((s) -> !s.equalsIgnoreCase("close"))
.orElse(true);
if (keepAlive && checkOpen()) {
Log.logTrace("Returning connection to the pool: {0}", this);
pool.returnToPool(this);
} else {
Log.logTrace("Closing connection (keepAlive={0}, isOpen={1}): {2}",
keepAlive, isOpen(), this);
close();
}
}以上就是java.net.http.HttpClient使用示例解析的詳細(xì)內(nèi)容,更多關(guān)于java.net.http.HttpClient的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java實(shí)現(xiàn)權(quán)重隨機(jī)算法詳解
平時(shí),經(jīng)常會(huì)遇到權(quán)重隨機(jī)算法,從不同權(quán)重的N個(gè)元素中隨機(jī)選擇一個(gè),并使得總體選擇結(jié)果是按照權(quán)重分布的。本文就詳細(xì)來(lái)介紹如何實(shí)現(xiàn),感興趣的可以了解一下2021-07-07
SpringBoot集成Spring Security的方法
Spring security,是一個(gè)強(qiáng)大的和高度可定制的身份驗(yàn)證和訪問(wèn)控制框架。這篇文章主要介紹了SpringBoot集成Spring Security的操作方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-07-07
淺談為什么同一個(gè)java文件只能有一個(gè)public類
這篇文章主要介紹了淺談為什么同一個(gè)java文件只能有一個(gè)public類,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-11-11
java?AES加密/解密實(shí)現(xiàn)完整代碼(附帶源碼)
這篇文章主要介紹了java?AES加密/解密實(shí)現(xiàn)的相關(guān)資料,包括AES加密算法的基本原理、Java加密API的使用方法以及項(xiàng)目實(shí)現(xiàn)的步驟和代碼示例,需要的朋友可以參考下2025-04-04
SpringBoot打印詳細(xì)啟動(dòng)異常信息
這篇文章主要介紹了SpringBoot打印詳細(xì)啟動(dòng)異常信息,本文包含了詳細(xì)的過(guò)程解析與案例,概要的說(shuō)明了如何去使用打印啟動(dòng)異常信息,需要的朋友可以參考下2021-06-06
java線程池對(duì)象ThreadPoolExecutor的深入講解
在我們的開(kāi)發(fā)中“池”的概念并不罕見(jiàn),有數(shù)據(jù)庫(kù)連接池、線程池、對(duì)象池、常量池等等。下面這篇文章主要給大家介紹了關(guān)于java線程池對(duì)象ThreadPoolExecutor的相關(guān)資料,需要的朋友可以參考借鑒,下面來(lái)一起看看吧2018-09-09
一文盤(pán)點(diǎn)Java中常見(jiàn)內(nèi)存泄漏場(chǎng)景與解決方法
內(nèi)存泄漏 是指對(duì)象 已經(jīng)不再被程序使用,但因?yàn)槟承┰?nbsp;無(wú)法被垃圾回收器回收,長(zhǎng)期占用內(nèi)存,最終可能引發(fā)?OOM,本文會(huì)介紹常見(jiàn)的幾類內(nèi)存泄漏場(chǎng)景,大家可以避免一下2025-12-12
Spring Cloud Alibaba 本地調(diào)試介紹及方案設(shè)計(jì)
為了解決 本地調(diào)試 的問(wèn)題,本文實(shí)現(xiàn)了一種簡(jiǎn)單實(shí)用的策略,可以通過(guò) Nacos 動(dòng)態(tài)配置服務(wù)路由,還可以基于用戶,部門(mén),組織等級(jí)別配置服務(wù)路由,實(shí)現(xiàn) 本地調(diào)試 的同時(shí),實(shí)際上也實(shí)現(xiàn) 灰度發(fā)布,感興趣的朋友跟隨小編一起看看吧2021-07-07

