国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Java11 HttpClient小試牛刀

Bmob / 1609人閱讀

本文主要研究一下Java11的HttpClient的基本使用。

變化

從java9的jdk.incubator.httpclient模塊遷移到j(luò)ava.net.http模塊,包名由jdk.incubator.http改為java.net.http

原來(lái)的諸如HttpResponse.BodyHandler.asString()方法變更為HttpResponse.BodyHandlers.ofString(),變化一為BodyHandler改為BodyHandlers,變化二為asXXX()之類的方法改為ofXXX(),由as改為of

實(shí)例 設(shè)置超時(shí)時(shí)間
    @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 response =
                client.send(request, HttpResponse.BodyHandlers.ofString());

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

    }

HttpConnectTimeoutException實(shí)例

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實(shí)例

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)
設(shè)置authenticator
    @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 response =
                client.send(request, HttpResponse.BodyHandlers.ofString());

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

authenticator可以用來(lái)設(shè)置HTTP authentication,比如Basic authentication

雖然Basic authentication也可以自己設(shè)置header,不過(guò)通過(guò)authenticator省得自己去構(gòu)造header

設(shè)置header
    @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 response =
                client.send(request, HttpResponse.BodyHandlers.ofString());

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

通過(guò)request可以自己設(shè)置header

GET

同步

    @Test
    public void testSyncGet() throws IOException, InterruptedException {
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://www.baidu.com"))
                .build();

        HttpResponse response =
                client.send(request, HttpResponse.BodyHandlers.ofString());

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

異步

    @Test
    public void testAsyncGet() throws ExecutionException, InterruptedException {
        HttpClient client = HttpClient.newHttpClient();
        HttpRequest request = HttpRequest.newBuilder()
                .uri(URI.create("https://www.baidu.com"))
                .build();

        CompletableFuture result = client.sendAsync(request, HttpResponse.BodyHandlers.ofString())
                .thenApply(HttpResponse::body);
        System.out.println(result.get());
    }
POST表單
    @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 response = client.send(request, HttpResponse.BodyHandlers.ofString());
        System.out.println(response.statusCode());
    }

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

POST JSON
    @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 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格式

文件上傳
    @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) //要設(shè)置,否則阻塞
                .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 response =
                client.send(request, HttpResponse.BodyHandlers.ofString());

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

官方的HttpClient并沒(méi)有提供類似WebClient那種現(xiàn)成的BodyInserters.fromMultipartData方法,因此這里需要自己轉(zhuǎn)換

這里使用org.apache.httpcomponents(httpclient及httpmime)的MultipartEntityBuilder構(gòu)建multipartEntity,最后通過(guò)HttpRequest.BodyPublishers.ofInputStream來(lái)傳遞內(nèi)容

這里header要指定Content-Type值為multipart/form-data以及boundary的值,否則服務(wù)端可能無(wú)法解析

文件下載
    @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 result = client.sendAsync(request, HttpResponse.BodyHandlers.ofFile(Paths.get("/tmp/body.txt")))
                .thenApply(HttpResponse::body);
        System.out.println(result.get());
    }

使用HttpResponse.BodyHandlers.ofFile來(lái)接收文件

并發(fā)請(qǐng)求
    @Test
    public void testConcurrentRequests(){
        HttpClient client = HttpClient.newHttpClient();
        List urls = List.of("http://www.baidu.com","http://www.alibaba.com/","http://www.tencent.com");
        List requests = urls.stream()
                .map(url -> HttpRequest.newBuilder(URI.create(url)))
                .map(reqBuilder -> reqBuilder.build())
                .collect(Collectors.toList());

        List>> 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,可以方便地進(jìn)行轉(zhuǎn)換、組合等操作

這里使用CompletableFuture.allOf組合在一起,最后調(diào)用join等待所有future完成

錯(cuò)誤處理
    @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 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異步請(qǐng)求返回的是CompletableFuture>,其自帶exceptionally方法可以用來(lái)做fallback處理

另外值得注意的是HttpClient不像WebClient那樣,它沒(méi)有對(duì)4xx或5xx的狀態(tài)碼拋出異常,需要自己根據(jù)情況來(lái)處理,手動(dòng)檢測(cè)狀態(tài)碼拋出異常或者返回其他內(nèi)容

HTTP2
    @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();
    }

執(zhí)行之后可以看到返回的response的version為HTTP_2

WebSocket
    @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,通過(guò)newWebSocketBuilder去構(gòu)造WebSocket

傳入listener進(jìn)行接收消息,要發(fā)消息的話,使用WebSocket來(lái)發(fā)送,關(guān)閉使用sendClose方法

reactive streams

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

public static class ByteArraySubscriber implements BodySubscriber {
        private final Function finisher;
        private final CompletableFuture result = new MinimalFuture<>();
        private final List received = new ArrayList<>();

        private volatile Flow.Subscription subscription;

        public ByteArraySubscriber(Function 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 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 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 getBody() {
            return result;
        }
    }

BodySubscriber接口繼承了Flow.Subscriber>接口

這里的Subscription來(lái)自Flow類,該類是java9引入的,里頭包含了支持Reactive Streams的實(shí)現(xiàn)

小結(jié)

HttpClient在Java11從incubator變?yōu)檎桨妫鄬?duì)于傳統(tǒng)的HttpUrlConnection其提升可不是一點(diǎn)半點(diǎn),不僅支持異步,也支持reactive streams,同時(shí)也支持了HTTP2以及WebSocket,非常值得大家使用。

doc

java.net.http javadoc

Examples and Recipes

Java 11: Standardized HTTP Client API

Exploring the New HTTP Client in Java 9

Introduction to the New HTTP Client in Java 9

Getting Started With Java 9"s New HTTP Client

java9系列(六)HTTP/2 Client (Incubator)

Java 9 HttpClient send a multipart/form-data request

Java 9: High level HTTP and WebSocket API

WebSocket Client API in Java 9 with Example

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/77327.html

相關(guān)文章

  • Java11的新特性

    摘要:從版本開(kāi)始,不再單獨(dú)發(fā)布或者版本了,有需要的可以自己通過(guò)去定制官方解讀官方細(xì)項(xiàng)解讀穩(wěn)步推進(jìn)系列六的小試牛刀一文讀懂的為何如此高效棄用引擎 Java語(yǔ)言特性系列 Java5的新特性 Java6的新特性 Java7的新特性 Java8的新特性 Java9的新特性 Java10的新特性 Java11的新特性 Java12的新特性 Java13的新特性 序 本文主要講述一下Java11的新...

    April 評(píng)論0 收藏0
  • webmagic小試牛刀

    摘要:序是里頭比較優(yōu)秀的一個(gè)爬蟲框架使用作為解析工具,并基于其開(kāi)發(fā)了解析的工具。默認(rèn)使用了作為下載工具。這里展示一下入門級(jí)使用。 序 webmagic是java里頭比較優(yōu)秀的一個(gè)爬蟲框架: 使用Jsoup作為HTML解析工具,并基于其開(kāi)發(fā)了解析XPath的工具Xsoup。 默認(rèn)使用了Apache HttpClient作為下載工具。 這里展示一下入門級(jí)使用。 maven ...

    stefan 評(píng)論0 收藏0
  • 從JDK11新增HttpClient談?wù)劮亲枞P?/b>

    摘要:是一個(gè)倡議,它提倡提供一種帶有非阻塞背壓的異步流處理的標(biāo)準(zhǔn)。是標(biāo)準(zhǔn)的實(shí)現(xiàn)之一。的實(shí)現(xiàn)細(xì)節(jié)請(qǐng)求響應(yīng)的與請(qǐng)求響應(yīng)的暴露為是請(qǐng)求的的消費(fèi)者是響應(yīng)的的生產(chǎn)者內(nèi)部的內(nèi)部 北京時(shí)間 9 月 26 日,Oracle 官方宣布 Java 11 正式發(fā)布 一、JDK HTTP Client介紹 JDK11中的17個(gè)新特性 showImg(https://segmentfault.com/img/remo...

    pingan8787 評(píng)論0 收藏0
  • 淺析 jdk11HttpClient 的使用

    摘要:在中也可以直接使用返回的是,然后通過(guò)來(lái)獲取結(jié)果阻塞線程,從中獲取結(jié)果四一點(diǎn)嘮叨非常的年輕,網(wǎng)絡(luò)資料不多,且代碼非常精細(xì)和復(fù)雜,目前來(lái)看底層應(yīng)該是使用了線程池搭配進(jìn)行異步通訊。 零 前期準(zhǔn)備 0 版本 JDK 版本 : OpenJDK 11.0.1 IDE : idea 2018.3 1 HttpClient 簡(jiǎn)介 java.net.http.HttpClient 是 jdk11 中正式...

    Eminjannn 評(píng)論0 收藏0
  • Java 11 教程

    摘要:原文鏈接已于成功發(fā)布,不過(guò)目前絕大多數(shù)人在生產(chǎn)環(huán)境仍舊使用的是。這篇以案例為主的教程涵蓋了從到的絕大多數(shù)重要的語(yǔ)法與特性。當(dāng)編譯器不能正確識(shí)別出變量的數(shù)值類型時(shí),將不被允許使用。同步請(qǐng)求將會(huì)阻塞當(dāng)前的線程,直到返回響應(yīng)消息。 showImg(https://segmentfault.com/img/remote/1460000016575203); 原文鏈接:https://wangw...

    douzifly 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<