Java9 HTTP2.0 API入門與實(shí)踐

簡述

如果您需要使用Java語言來請求HTTP資源肤视,那么你可能會(huì)遇到多種解決方案,你最終可能會(huì)以一種合理的方式來達(dá)成這個(gè)目的 —– 引用第三方包已卷。
好消息弧哎,好消息雁比,黃鶴帶著小姨子回來了,皮革廠有救了:Java9除了有模塊化特性之外撤嫩,還附帶了一個(gè)全新的HTTP客戶端API偎捎。不僅支持HTTP2.0,還提供了一套有親和力的API序攘。SO茴她,讓我們來剝掉小姨子神秘的蕾絲面紗。

HTTP2.0是啥子?xùn)|東程奠?

HTTP2.0帶來了令人手舞足蹈的新特性:(這里不來自原文)

  • 二進(jìn)制分幀
  • 請求/響應(yīng)管線化
  • 異步連接
  • 多路復(fù)用
  • 服務(wù)器推送流(Server Push技術(shù))
  • 基于TCP的長連接
  • 首部壓縮

一句話描述:http/2最大的特點(diǎn)是使用多路復(fù)用丈牢,對(duì)同一個(gè)域的服務(wù)器只建立一次TCP連接,加載多個(gè)資源瞄沙,使用二進(jìn)制幀傳輸己沛,同時(shí)會(huì)對(duì)http頭部進(jìn)行壓縮。
就這樣距境,我們瞧上了豐滿的HTTP2.0申尼。

Incubator 模塊

這里需要注意的是,在Java9中HTTP客戶端的構(gòu)建需要依賴于一個(gè)Incubator模塊垫桂,and more:

  • 在 JDK 9, 這個(gè)模塊叫做jdk.incubator.httpclient
  • incubator模塊在JDK10將被java.httpclient所取代
  • JDK10在這方面將迎來重大突破(現(xiàn)在誰知道师幕?)

Java 9的HTTP客戶端API

基本上,通過HTTP進(jìn)行通信時(shí)诬滩,會(huì)涉及到三個(gè)類:HttpClient將用于發(fā)送HttpRequest和接收HttpResponse霹粥。這API還是比較容易理解的灭将,right? Let’s see:
基本示例:GET 請求,返回字符串

HttpClient client = HttpClient.newHttpClient();

HttpRequest request = HttpRequest.newBuilder()
    .uri(new URI("https://labs.consol.de/"))
    .build();

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandler.asString());

System.out.println(response.statusCode());
System.out.println(response.body());

很優(yōu)雅后控,對(duì)不對(duì)宗侦? 沒有InputStream和Reader被涉及, - 轉(zhuǎn)而是通過BodyHandler來直接從響應(yīng)中獲取字符串忆蚀。不多贅述,將在下文介紹BodyHandlers姑裂。
雖然HttpClient馋袜,HttpRequest并且HttpResponse是HTTP2.0通信中的主要參與者,但我們還是要與Builder配合使用舶斧。Builder提供了一套簡明易懂的API欣鳖。

HttpRequest.Builder

我們可以通過調(diào)用HttpRequest.newBuilder()來獲取一個(gè)HttpRequest.Builder實(shí)例,就像第一個(gè)示例中那樣茴厉。 我們將使用它來配置與特定請求相關(guān)的所有內(nèi)容泽台。下面是源代碼:

// HttpRequest.Builder
public abstract static class Builder {
    // note: some methods left out for the sake of brevity
    public abstract Builder uri(URI uri);
    public abstract Builder version(HttpClient.Version version);
    public abstract Builder header(String name, String value);
    public abstract Builder timeout(Duration duration);
    public abstract Builder GET();
    public abstract Builder POST(BodyProcessor body);
    public abstract Builder PUT(BodyProcessor body);
    public abstract Builder DELETE(BodyProcessor body);
    public abstract HttpRequest build();
}

可讀性很好(自解釋型), right? 采用鏈?zhǔn)椒椒ㄕ{(diào)用來完成請求內(nèi)容的配置矾缓,然后調(diào)用build()獲取HttpRequest實(shí)例怀酷。

HttpClient.Builder

與HttpRequest類似,我們調(diào)用HttpClient.newBuilder()來獲取HttpClient.Builder實(shí)例嗜闻。它提供了一個(gè)API來配置一些關(guān)于我們的連接的更通用的東西蜕依。 下面是源代碼:

// HttpClient.Builder
public abstract static class Builder {
    public abstract Builder cookieManager(CookieManager cookieManager);
    public abstract Builder sslContext(SSLContext sslContext);
    public abstract Builder sslParameters(SSLParameters sslParameters);
    public abstract Builder executor(Executor executor);
    public abstract Builder followRedirects(Redirect policy);
    public abstract Builder version(HttpClient.Version version);
    public abstract Builder priority(int priority);
    public abstract Builder proxy(ProxySelector selector);
    public abstract Builder authenticator(Authenticator a);
    public abstract HttpClient build();
}

真是通體雪白!琉雳!良好的自解釋性幫助IDE能夠更好地達(dá)成你的目的样眠。

更多Java 9 HTTP客戶端應(yīng)用示例

上面見識(shí)到了這套前景光明的API,下面讓我們來看看更多的關(guān)于它的應(yīng)用示例吧翠肘。

1. 保存GET請求到文件

HttpClient client = HttpClient.newHttpClient();

HttpRequest request = HttpRequest.newBuilder()
    .uri(new URI("https://labs.consol.de/"))
    .GET()
    .build();

Path tempFile = Files.createTempFile("consol-labs-home", ".html");
HttpResponse<Path> response = client.send(request, HttpResponse.BodyHandler.asFile(tempFile));
System.out.println(response.statusCode());
System.out.println(response.body());

2. 通過POST上傳文件

用POST上傳本地文件也變得十分簡單檐束,使用HttpRequest.BodyProcessor:

HttpClient client = HttpClient.newHttpClient();

HttpRequest request = HttpRequest.newBuilder()
    .uri(new URI("http://localhost:8080/upload/"))
    .POST(HttpRequest.BodyProcessor.fromFile(Paths.get("/tmp/file-to-upload.txt")))
    .build();

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandler.discard(null));
System.out.println(response.statusCode());

3. 異步HTTP請求

異步HTTP請求也變得簡單,由HttpClient#sendAsync()代替HttpClient#send束倍。如果服務(wù)端支持被丧,你甚至可以取消執(zhí)行中的請求:

HttpClient client = HttpClient.newHttpClient();

HttpRequest request = HttpRequest.newBuilder()
    .uri(new URI("https://labs.consol.de/"))
    .GET()
    .build();

CompletableFuture<HttpResponse<String>> response = client.sendAsync(request, HttpResponse.BodyHandler.asString());

Thread.sleep(5000);
if(response.isDone()) {
    System.out.println(response.get().statusCode());
    System.out.println(response.get().body());
} else {
    response.cancel(true);
    System.out.println("Request took more than 5 seconds... cancelling.");
}

4. 使用系統(tǒng)代理設(shè)置

HttpClient client = HttpClient.newBuilder()
 
     .proxy(ProxySelector.getDefault())
     .build();

 HttpRequest request = HttpRequest.newBuilder()
     .uri(new URI("https://labs.consol.de"))
     .GET()
     .build();

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandler.asString());
 System.out.println(response.statusCode());
 System.out.println(response.body());

5.基本認(rèn)證 Basic Authentication

HttpClient client = HttpClient.newBuilder()
    .authenticator(new Authenticator() {
        @Override
        protected PasswordAuthentication getPasswordAuthentication() {
            return new PasswordAuthentication("username", "password".toCharArray());
        }
    })
    .build();

HttpRequest request = HttpRequest.newBuilder()
    .uri(new URI("https://labs.consol.de"))
    .GET()
    .build();

HttpResponse<String> response = client.send(request, HttpResponse.BodyHandler.asString());
System.out.println(response.statusCode());
System.out.println(response.body());

結(jié)論

上面的例子表明,使用Java 9的標(biāo)準(zhǔn)API來發(fā)送HTTP請求會(huì)更簡便肌幽。 此外晚碾,我們將能以優(yōu)雅的方式處理響應(yīng)。當(dāng)然喂急,某些三方包也有類似喜人的功能格嘁,但總得選擇一種體面的(decent)開箱即用的解決方案(大家閨秀即視感,2333)廊移。
英文原文

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末糕簿,一起剝皮案震驚了整個(gè)濱河市探入,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌懂诗,老刑警劉巖蜂嗽,帶你破解...
    沈念sama閱讀 219,270評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異殃恒,居然都是意外死亡植旧,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門离唐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來病附,“玉大人,你說我怎么就攤上這事亥鬓⊥昊Γ” “怎么了?”我有些...
    開封第一講書人閱讀 165,630評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵嵌戈,是天一觀的道長覆积。 經(jīng)常有香客問我,道長熟呛,這世上最難降的妖魔是什么宽档? 我笑而不...
    開封第一講書人閱讀 58,906評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮惰拱,結(jié)果婚禮上雌贱,老公的妹妹穿的比我還像新娘。我一直安慰自己偿短,他們只是感情好欣孤,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著昔逗,像睡著了一般降传。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上勾怒,一...
    開封第一講書人閱讀 51,718評(píng)論 1 305
  • 那天婆排,我揣著相機(jī)與錄音,去河邊找鬼笔链。 笑死段只,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的鉴扫。 我是一名探鬼主播赞枕,決...
    沈念sama閱讀 40,442評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了炕婶?” 一聲冷哼從身側(cè)響起姐赡,我...
    開封第一講書人閱讀 39,345評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎柠掂,沒想到半個(gè)月后项滑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡涯贞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評(píng)論 3 337
  • 正文 我和宋清朗相戀三年枪狂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宋渔。...
    茶點(diǎn)故事閱讀 40,117評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡摘完,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出傻谁,到底是詐尸還是另有隱情,我是刑警寧澤列粪,帶...
    沈念sama閱讀 35,810評(píng)論 5 346
  • 正文 年R本政府宣布审磁,位于F島的核電站,受9級(jí)特大地震影響岂座,放射性物質(zhì)發(fā)生泄漏态蒂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評(píng)論 3 331
  • 文/蒙蒙 一费什、第九天 我趴在偏房一處隱蔽的房頂上張望钾恢。 院中可真熱鬧,春花似錦鸳址、人聲如沸瘩蚪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽疹瘦。三九已至,卻和暖如春巡球,著一層夾襖步出監(jiān)牢的瞬間言沐,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評(píng)論 1 272
  • 我被黑心中介騙來泰國打工酣栈, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留险胰,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,377評(píng)論 3 373
  • 正文 我出身青樓矿筝,卻偏偏與公主長得像起便,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理缨睡,服務(wù)發(fā)現(xiàn)鸟悴,斷路器,智...
    卡卡羅2017閱讀 134,667評(píng)論 18 139
  • 聽了漲工資的事奖年,對(duì)我內(nèi)心的無節(jié)操真真地給跪了细诸。不然就屈服了吧?
    瞳亻閱讀 482評(píng)論 0 1
  • 我認(rèn)為陋守、只要有夢想震贵、有實(shí)干精神、能堅(jiān)持不懈的努力水评。夢想終究會(huì)成為現(xiàn)實(shí)猩系。就像黃宗孟一樣、從最開始的算命開始中燥。至今已經(jīng)...
    貴州黃宗孟導(dǎo)演閱讀 273評(píng)論 0 1
  • 這是一份很牛很牛的攝影教程 無論你是自學(xué)攝影還是正在學(xué)攝影的路上 都能為你答疑解惑寇甸! 趕快看下都有什么吧! 這套攝...
    醐說閱讀 283評(píng)論 0 0