JDK11新特性 --httpClient

JDK11新特性 --httpClient

一:HttpURLConnenction目前存在的問題

1.其基類 URLConnection 當(dāng)初是設(shè)計(jì)為支持多協(xié)議杀狡,但其中大多已經(jīng)成為非主流(ftp, gopher…)
2.API 的設(shè)計(jì)早于 HTTP/1.1然磷,過度抽象
3.難以使用,存在許多沒有文檔化的行為
4.它只支持阻塞模式(每個(gè)請(qǐng)求 / 響應(yīng)占用一個(gè)線程)

二: HttpClient簡(jiǎn)介

httpclient是Apache Jakarta common下的子項(xiàng)目谓媒,用來提供高效的饺著、最新的、更能豐富的支持http協(xié)議的客戶端編程工具包抑月,并且它支持http協(xié)議最新的版本和建議。httpclient已經(jīng)應(yīng)用在很多項(xiàng)目中舆蝴,比如Apache Jakarta上很著名的兩個(gè)開源項(xiàng)目cactus和httplunit都使用了httpclient谦絮。

三:HttpClient特性

1.以可擴(kuò)展的面向?qū)ο蟮慕Y(jié)構(gòu)實(shí)現(xiàn)了HTTP全部的方法(GET、POST洁仗、put层皱、delete、head赠潦、options奶甘、trace)。

2.支持HTTPS協(xié)議祭椰。

3.通過HTTP代理建立透明的連接臭家。
4.連接管理器支持多線程應(yīng)用。支持設(shè)置最大連接數(shù)方淤,同事支持設(shè)置每個(gè)主機(jī)的最大連接數(shù)钉赁,發(fā)現(xiàn)并關(guān)閉過期的連接。

5.自動(dòng)處理Set-Cookie中的Cookie携茂。

6.插件式的自定義Cookie策略你踩。

7.request的輸出流可以避免流中內(nèi)容直接緩沖到socket服務(wù)器。

8.Response的輸入流可以有效的從socket服務(wù)器直接讀取相應(yīng)內(nèi)容

三:使用方法

使用HttpClient發(fā)送請(qǐng)求讳苦、接收響應(yīng)很簡(jiǎn)單带膜,一般需要如下幾步即可。
1鸳谜、創(chuàng)建httpclient對(duì)象膝藕。
2、創(chuàng)建請(qǐng)求方法的實(shí)例咐扭,并制定請(qǐng)求url芭挽。如果需要發(fā)送get請(qǐng)求,創(chuàng)建httpclient對(duì)象蝗肪;如果需要發(fā)送post請(qǐng)求袜爪,創(chuàng)建httpPOST對(duì)象。
3薛闪、如果需要發(fā)送請(qǐng)求參數(shù)辛馆,可調(diào)用httpget、httpPost共同的setparams(HetpParams params)方法來添加請(qǐng)求參數(shù)豁延;對(duì)于HttpPost對(duì)象而言昙篙,也可調(diào)用setEntity(HttpEntity entity)方法來設(shè)置請(qǐng)求參數(shù)倔韭。
4、調(diào)用HttpClient對(duì)象的execute(HttpUriRequest request)發(fā)送請(qǐng)求瓢对,該方法返回一個(gè)HttpResponse寿酌。
5、調(diào)用HttpResponse的getAllHeaders()硕蛹、getHeaders(String name)等方法可獲取服務(wù)器的響應(yīng)頭醇疼;調(diào)用HttpResponse的getEntity()方法可獲取HttpEntity對(duì)象,該對(duì)象包裝了服務(wù)器的響應(yīng)內(nèi)容法焰。程序可通過該對(duì)象獲取服務(wù)器的響應(yīng)內(nèi)容秧荆。
6、釋放連接埃仪。無論執(zhí)行方法是否成功乙濒,都必須釋放連接

四:代碼實(shí)例

實(shí)例1:同步get請(qǐng)求

public void syncGet() throws InterruptedException, IOException {

    HttpClient client = HttpClient.newHttpClient();
    HttpRequest request = HttpRequest.newBuilder().uri(URI.create("https://www.baidu.com")).build();
    HttpResponse<String> response =
            client.send(request, HttpResponse.BodyHandlers.ofString());

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

實(shí)例2:異步Get 請(qǐng)求

    HttpClient client = HttpClient.newHttpClient();
    HttpRequest request = HttpRequest.newBuilder().uri(URI.create("https://www.baidu.com")).build();
    CompletableFuture<String> result = client.sendAsync(request, HttpResponse.BodyHandlers.ofString()).thenApply(HttpResponse::body);
    System.out.println(result.get());

}

實(shí)例四:Post請(qǐng)求

    HttpClient client = HttpClient.newBuilder().build();
    HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create("http://www.w3school.com.cn/demo/demo_form.asp"))
            .header("Content-Type","application/x-www-form-urlencoded")
            .POST(HttpRequest.BodyPublishers.ofString("name1=value1&name2=value2"))
            .build();

    HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
    System.out.println(response.statusCode());
}

實(shí)例五:JSON傳參 header指定內(nèi)容是表單類型,然后通過BodyPublishers.ofString傳遞表單數(shù)據(jù)卵蛉,需要自己構(gòu)建表單參數(shù)

ObjectMapper objectMapper = new ObjectMapper();
StockDto dto = new StockDto();
dto.setName("hj");
dto.setSymbol("hj");
dto.setType(StockDto.StockType.SH);
String requestBody = objectMapper
.writerWithDefaultPrettyPrinter()
.writeValueAsString(dto);

     HttpRequest request = HttpRequest.newBuilder(URI.create("http://localhost:8080/json/demo"))
       .header("Content-Type", "application/json")
       .POST(HttpRequest.BodyPublishers.ofString(requestBody))
       .build();
     
     CompletableFuture<StockDto> result = HttpClient.newHttpClient()
       .sendAsync(request, HttpResponse.BodyHandlers.ofString())
       .thenApply(HttpResponse::body)
       .thenApply(body -> {
        try {
         return objectMapper.readValue(body,StockDto.class);
        } catch (IOException e) {
         return new StockDto();
        }
       });StockDto

System.out.println(result.get());
實(shí)例六:并發(fā)請(qǐng)求

//endAsync方法返回的是CompletableFuture颁股,可以方便地進(jìn)行轉(zhuǎn)換、組合等操作
//這里使用CompletableFuture.allOf組合在一起傻丝,最后調(diào)用join等待所有future完成
public void testConcurrentRequests(){
HttpClient client = HttpClient.newHttpClient();
List<String> urls = List.of("http://www.baidu.com","http://www.alibaba.com/","http://www.tencent.com");
List<HttpRequest> requests = urls.stream()
.map(url -> HttpRequest.newBuilder(URI.create(url)))
.map(reqBuilder -> reqBuilder.build())
.collect(Collectors.toList());

    List<CompletableFuture<HttpResponse<String>>> futures = requests.stream()
            .map(request -> client.sendAsync(request, HttpResponse.BodyHandlers.ofString()))
            .collect(Collectors.toList());
    futures.stream()
            .forEach(e -> e.whenComplete((resp,err) -> {
                if(err != null){
                    err.printStackTrace();
                }else{
                    System.out.println(resp.body());
                    System.out.println(resp.statusCode());
                }
            }));
    CompletableFuture.allOf(futures
            .toArray(CompletableFuture<?>[]::new))
            .join();


}

六:總結(jié)

HttpClient中常用到的類

HttpClient
|-- DefaultHttpClient
構(gòu)造方法: DefaultHttpClient
主要方法: HttpResponse execute(HttpUriRequest request)
HttpUriRequest
|-- HttpGet
構(gòu)造方法: HttpGet()
HttpGet(String uri)
|-- HttpPost
構(gòu)造方法: HttpPost(String uri)
主要方法: void setEntity(HttpEntity entity)
HttpResponse
主要方法:
StatusLine getStatusLine()
Header[] getAllHeaders();
HttpEntity getEntity();
HttpEntity
主要方法:
InputStream getContent();
long getContentLength();
Header getContentType();
|-- UrlEncodedFormEntity
構(gòu)造方法:UrlEncodedFormEntity(List<? extends NameValuePair> params)
//用于向請(qǐng)求對(duì)象中寫入請(qǐng)求實(shí)體(包含請(qǐng)求參數(shù)(NameValuePair))
EntityUtils
public static byte[] toByteArray(HttpEntity entity)
public static String toString(HttpEntity entity)
public static String toString(HttpEntity entity , String encoding)
StatusLine
int getStatusCode()
HttpStatus
SC_OK SC_NOT_FOUND
Header
String getName()
String getValue()
NameValuePair
String getName()
String getValue()
|-- BasicNameValuePair
構(gòu)造方法:BasicNameValuePair(String name , String value)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末甘有,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子葡缰,更是在濱河造成了極大的恐慌亏掀,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件泛释,死亡現(xiàn)場(chǎng)離奇詭異滤愕,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)怜校,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門间影,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人韭畸,你說我怎么就攤上這事宇智。” “怎么了胰丁?”我有些...
    開封第一講書人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長喂分。 經(jīng)常有香客問我锦庸,道長,這世上最難降的妖魔是什么蒲祈? 我笑而不...
    開封第一講書人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任甘萧,我火速辦了婚禮萝嘁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘扬卷。我一直安慰自己牙言,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開白布怪得。 她就那樣靜靜地躺著咱枉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪徒恋。 梳的紋絲不亂的頭發(fā)上蚕断,一...
    開封第一講書人閱讀 51,590評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音入挣,去河邊找鬼亿乳。 笑死,一個(gè)胖子當(dāng)著我的面吹牛径筏,可吹牛的內(nèi)容都是我干的葛假。 我是一名探鬼主播,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼滋恬,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼桐款!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起夷恍,我...
    開封第一講書人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤魔眨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后酿雪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體遏暴,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年指黎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了朋凉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡醋安,死狀恐怖杂彭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情吓揪,我是刑警寧澤亲怠,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站柠辞,受9級(jí)特大地震影響团秽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一习勤、第九天 我趴在偏房一處隱蔽的房頂上張望踪栋。 院中可真熱鬧,春花似錦图毕、人聲如沸夷都。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽囤官。三九已至,卻和暖如春荣瑟,著一層夾襖步出監(jiān)牢的瞬間治拿,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來泰國打工笆焰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留劫谅,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓嚷掠,卻偏偏與公主長得像捏检,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子不皆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

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