国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Java11新特性之HttpClient小試牛刀

Java11新特性之HttpClient小試牛刀

2021-06-02 13:50codecraft Java教程

本文主要研究一下Java11的HttpClient的基本使用。小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

本文主要研究一下java11的httpclient的基本使用。

變化

  1. 從java9的jdk.incubator.httpclient模塊遷移到java.net.http模塊,包名由jdk.incubator.http改為java.net.http
  2. 原來的諸如httpresponse.bodyhandler.asstring()方法變更為httpresponse.bodyhandlers.ofstring(),變化一為bodyhandler改為bodyhandlers,變化二為asxxx()之類的方法改為ofxxx(),由as改為of

實例

設置超時時間

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@test
public void testtimeout() throws ioexception, interruptedexception {
 //1.set connect timeout
 httpclient client = httpclient.newbuilder()
   .connecttimeout(duration.ofmillis(5000))
   .followredirects(httpclient.redirect.normal)
   .build();
 
 //2.set read timeout
 httprequest request = httprequest.newbuilder()
   .uri(uri.create("http://openjdk.java.net/"))
   .timeout(duration.ofmillis(5009))
   .build();
 
 httpresponse<string> response =
   client.send(request, httpresponse.bodyhandlers.ofstring());
 
 system.out.println(response.body());
 
}

httpconnecttimeoutexception實例

?
1
2
3
4
5
6
7
caused by: java.net.http.httpconnecttimeoutexception: http connect timed out
 at java.net.http/jdk.internal.net.http.responsetimerevent.handle(responsetimerevent.java:68)
 at java.net.http/jdk.internal.net.http.httpclientimpl.purgetimeoutsandreturnnextdeadline(httpclientimpl.java:1248)
 at java.net.http/jdk.internal.net.http.httpclientimpl$selectormanager.run(httpclientimpl.java:877)
caused by: java.net.connectexception: http connect timed out
 at java.net.http/jdk.internal.net.http.responsetimerevent.handle(responsetimerevent.java:69)
 ... 2 more

httptimeoutexception實例

?
1
2
3
4
5
java.net.http.httptimeoutexception: request timed out
 
 at java.net.http/jdk.internal.net.http.httpclientimpl.send(httpclientimpl.java:559)
 at java.net.http/jdk.internal.net.http.httpclientfacade.send(httpclientfacade.java:119)
 at com.example.httpclienttest.testtimeout(httpclienttest.java:40)

設置authenticator

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@test
public void testbasicauth() throws ioexception, interruptedexception {
 httpclient client = httpclient.newbuilder()
   .connecttimeout(duration.ofmillis(5000))
   .authenticator(new authenticator() {
    @override
    protected passwordauthentication getpasswordauthentication() {
     return new passwordauthentication("admin","password".tochararray());
    }
   })
   .build();
 
 httprequest request = httprequest.newbuilder()
   .uri(uri.create("http://localhost:8080/json/info"))
   .timeout(duration.ofmillis(5009))
   .build();
 
 httpresponse<string> response =
   client.send(request, httpresponse.bodyhandlers.ofstring());
 
 system.out.println(response.statuscode());
 system.out.println(response.body());
}
  1. authenticator可以用來設置http authentication,比如basic authentication
  2. 雖然basic authentication也可以自己設置header,不過通過authenticator省得自己去構造header

設置header

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@test
public void testcookies() throws ioexception, interruptedexception {
 httpclient client = httpclient.newbuilder()
   .connecttimeout(duration.ofmillis(5000))
   .build();
 httprequest request = httprequest.newbuilder()
   .uri(uri.create("http://localhost:8080/json/cookie"))
   .header("cookie","jsessionid=4f994730-32d7-4e22-a18b-25667ddeb636; userid=java11")
   .timeout(duration.ofmillis(5009))
   .build();
 httpresponse<string> response =
   client.send(request, httpresponse.bodyhandlers.ofstring());
 
 system.out.println(response.statuscode());
 system.out.println(response.body());
}

通過request可以自己設置header

get

同步

?
1
2
3
4
5
6
7
8
9
10
11
12
@test
public void testsyncget() throws ioexception, interruptedexception {
 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());
}

異步

?
1
2
3
4
5
6
7
8
9
10
11
@test
public void testasyncget() throws executionexception, interruptedexception {
 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());
}

post表單

?
1
2
3
4
5
6
7
8
9
10
11
12
@test
public void testpostform() throws ioexception, interruptedexception {
 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());
}

header指定內容是表單類型,然后通過bodypublishers.ofstring傳遞表單數據,需要自己構建表單參數

post json

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@test
public void testpostjsongetjson() throws executionexception, interruptedexception, jsonprocessingexception {
 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();
    }
   });
 system.out.println(result.get());
}

post json的話,body自己json化為string,然后header指定是json格式

文件上傳

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
@test
public void testuploadfile() throws ioexception, interruptedexception, urisyntaxexception {
 httpclient client = httpclient.newhttpclient();
 path path = path.of(getclass().getclassloader().getresource("body.txt").touri());
 file file = path.tofile();
 
 string multipartformdataboundary = "java11httpclientformboundary";
 org.apache.http.httpentity multipartentity = multipartentitybuilder.create()
   .addpart("file", new filebody(file, contenttype.default_binary))
   .setboundary(multipartformdataboundary) //要設置,否則阻塞
   .build();
 
 httprequest request = httprequest.newbuilder()
   .uri(uri.create("http://localhost:8080/file/upload"))
   .header("content-type", "multipart/form-data; boundary=" + multipartformdataboundary)
   .post(httprequest.bodypublishers.ofinputstream(() -> {
    try {
     return multipartentity.getcontent();
    } catch (ioexception e) {
     e.printstacktrace();
     throw new runtimeexception(e);
    }
   }))
   .build();
 
 httpresponse<string> response =
   client.send(request, httpresponse.bodyhandlers.ofstring());
 
 system.out.println(response.body());
}
  1. 官方的httpclient并沒有提供類似webclient那種現成的bodyinserters.frommultipartdata方法,因此這里需要自己轉換
  2. 這里使用org.apache.httpcomponents(httpclient及httpmime)的multipartentitybuilder構建multipartentity,最后通過httprequest.bodypublishers.ofinputstream來傳遞內容
  3. 這里header要指定content-type值為multipart/form-data以及boundary的值,否則服務端可能無法解析

文件下載

?
1
2
3
4
5
6
7
8
9
10
11
@test
public void testasyncdownload() throws executionexception, interruptedexception {
 httpclient client = httpclient.newhttpclient();
 httprequest request = httprequest.newbuilder()
   .uri(uri.create("http://localhost:8080/file/download"))
   .build();
 
 completablefuture<path> result = client.sendasync(request, httpresponse.bodyhandlers.offile(paths.get("/tmp/body.txt")))
   .thenapply(httpresponse::body);
 system.out.println(result.get());
}

使用httpresponse.bodyhandlers.offile來接收文件

并發請求

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@test
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();
}
  • sendasync方法返回的是completablefuture,可以方便地進行轉換、組合等操作
  • 這里使用completablefuture.allof組合在一起,最后調用join等待所有future完成

錯誤處理

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@test
 public void testhandleexception() throws executionexception, interruptedexception {
  httpclient client = httpclient.newbuilder()
    .connecttimeout(duration.ofmillis(5000))
    .build();
  httprequest request = httprequest.newbuilder()
    .uri(uri.create("https://twitter.com"))
    .build();
 
  completablefuture<string> result = client.sendasync(request, httpresponse.bodyhandlers.ofstring())
//    .whencomplete((resp,err) -> {
//     if(err != null){
//      err.printstacktrace();
//     }else{
//      system.out.println(resp.body());
//      system.out.println(resp.statuscode());
//     }
//    })
    .thenapply(httpresponse::body)
    .exceptionally(err -> {
     err.printstacktrace();
     return "fallback";
    });
  system.out.println(result.get());
 }
  • httpclient異步請求返回的是completablefuture<httpresponse<t>>,其自帶exceptionally方法可以用來做fallback處理
  • 另外值得注意的是httpclient不像webclient那樣,它沒有對4xx或5xx的狀態碼拋出異常,需要自己根據情況來處理,手動檢測狀態碼拋出異常或者返回其他內容

http2

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@test
public void testhttp2() throws urisyntaxexception {
 httpclient.newbuilder()
   .followredirects(httpclient.redirect.never)
   .version(httpclient.version.http_2)
   .build()
   .sendasync(httprequest.newbuilder()
       .uri(new uri("https://http2.akamai.com/demo"))
       .get()
       .build(),
     httpresponse.bodyhandlers.ofstring())
   .whencomplete((resp,t) -> {
    if(t != null){
     t.printstacktrace();
    }else{
     system.out.println(resp.version());
     system.out.println(resp.statuscode());
    }
   }).join();
}

執行之后可以看到返回的response的version為http_2

websocket

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@test
public void testwebsocket() throws interruptedexception {
 httpclient client = httpclient.newhttpclient();
 websocket websocket = client.newwebsocketbuilder()
   .buildasync(uri.create("ws://localhost:8080/echo"), new websocket.listener() {
 
    @override
    public completionstage<?> ontext(websocket websocket, charsequence data, boolean last) {
     // request one more
     websocket.request(1);
 
     // print the message when it's available
     return completablefuture.completedfuture(data)
       .thenaccept(system.out::println);
    }
   }).join();
 websocket.sendtext("hello ", false);
 websocket.sendtext("world ",true);
 
 timeunit.seconds.sleep(10);
 websocket.sendclose(websocket.normal_closure, "ok").join();
}
  • httpclient支持http2,也包含了websocket,通過newwebsocketbuilder去構造websocket
  • 傳入listener進行接收消息,要發消息的話,使用websocket來發送,關閉使用sendclose方法

reactive streams

httpclient本身就是reactive的,支持reactive streams,這里舉responsesubscribers.bytearraysubscriber的源碼看看:
java.net.http/jdk/internal/net/http/responsesubscribers.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
public static class bytearraysubscriber<t> implements bodysubscriber<t> {
  private final function<byte[], t> finisher;
  private final completablefuture<t> result = new minimalfuture<>();
  private final list<bytebuffer> received = new arraylist<>();
 
  private volatile flow.subscription subscription;
 
  public bytearraysubscriber(function<byte[],t> finisher) {
   this.finisher = finisher;
  }
 
  @override
  public void onsubscribe(flow.subscription subscription) {
   if (this.subscription != null) {
    subscription.cancel();
    return;
   }
   this.subscription = subscription;
   // we can handle whatever you've got
   subscription.request(long.max_value);
  }
 
  @override
  public void onnext(list<bytebuffer> items) {
   // incoming buffers are allocated by http client internally,
   // and won't be used anywhere except this place.
   // so it's free simply to store them for further processing.
   assert utils.hasremaining(items);
   received.addall(items);
  }
 
  @override
  public void onerror(throwable throwable) {
   received.clear();
   result.completeexceptionally(throwable);
  }
 
  static private byte[] join(list<bytebuffer> bytes) {
   int size = utils.remaining(bytes, integer.max_value);
   byte[] res = new byte[size];
   int from = 0;
   for (bytebuffer b : bytes) {
    int l = b.remaining();
    b.get(res, from, l);
    from += l;
   }
   return res;
  }
 
  @override
  public void oncomplete() {
   try {
    result.complete(finisher.apply(join(received)));
    received.clear();
   } catch (illegalargumentexception e) {
    result.completeexceptionally(e);
   }
  }
 
  @override
  public completionstage<t> getbody() {
   return result;
  }
 }
  1. bodysubscriber接口繼承了flow.subscriber<list<bytebuffer>>接口
  2. 這里的subscription來自flow類,該類是java9引入的,里頭包含了支持reactive streams的實現

小結

httpclient在java11從incubator變為正式版,相對于傳統的httpurlconnection其提升可不是一點半點,不僅支持異步,也支持reactive streams,同時也支持了http2以及websocket,非常值得大家使用。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。

原文鏈接:https://segmentfault.com/a/1190000016555671

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 免费成人激情视频 | 蜜桃精品久久久久久久免费影院 | 欧美一区二区高清视频 | 精品一区二区不卡 | 啪啪伊人网 | 一区自拍 | 中字精品 | 四虎影院最新地址 | 久久亚洲欧美日韩精品专区 | 一级做a爰片性色毛片2021 | 日韩中文字幕免费在线播放 | 国产精品69毛片高清亚洲 | 黄色影视在线免费观看 | 日韩亚洲| 精品精品| 综合久久久 | 特级毛片在线 | 青青久草 | 亚洲一区二区免费视频 | 亚洲字幕网 | 国产精品1区2区 | 国产精品久久久久久久久久久久午夜片 | 日韩免费视频 | 国产日产久久高清欧美一区 | 国产电影一区二区三区 | 日韩在线播放一区二区 | 欧美啪啪一区二区 | 日韩黄网站 | 深夜视频在线 | 国产精品久久久久久福利一牛影视 | 欧美日韩在线观看视频 | 久久不色 | 亚洲男人一区 | 久久亚洲一区 | 激情视频综合网 | 欧美日韩一区二区三区在线观看 | 凹凸日日摸日日碰夜夜爽孕妇 | 亚洲精品视频专区 | 国产一级特黄 | 亚洲成av人片在线观看无 | 午夜午夜精品一区二区三区文 |