Руководство по Java 9. HTTP 2.

В данной статье мы рассмотрим поддержку HTTP 2 в Java 9. HTTP 2  – это новая версия HTTP, в котором акцент сделан на то, как именно данные упаковываются и передаются от клиента к серверу и наоборот.

Среди преимуществ HTTP 2 можно выделить следующие:

  • Мультиплексирование
    HTTP  2 может отправлять несколько запросов данных параллельно, используя одно TCP соединение. В HTTP 1.1 мы не можем использовать более 6 открытых соединений одновременно.
  • Замена текста на Binary
  • Server Push
    При работе с HTTP 1.1 страницы пересылаются на клиент (браузеру) и он должен парсить HTML. Во время этого процесса, клиент может запрашивать дополнительные данные от сервера. В HTTP 2 сервер может отправлять эти данные без запроса от клиента

В новом API мы имеем возможность работать с HTTP соединениями, используя 3 класса:

  • HttpRequest
    используется для создания HTTP запроса от клиента к серверу
  • HttpResponse
    содержит HTTP ответ от сервера
  • HttpClient
    отвечает за обработку и отправку HTTP запросов

Рассмотрим небольшой пример:

Добавим в корневую директорию файл module-info.java:


module net.proselyte.java9 {
    requires jdk.incubator.httpclient;
}

Это необходимо для импорта в наш текущий модуль jdk.incubator.httpclient.

package net.proselyte.java9;

import jdk.incubator.http.*;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

public class Http2Demo {
    public static void main(String[] args) throws URISyntaxException, IOException, InterruptedException {
        HttpClient httpClient = HttpClient.newHttpClient();
        System.out.println("httpClient version: " + httpClient.version());

        HttpRequest httpRequest = HttpRequest.newBuilder().uri(new URI("https://www.google.com/")).GET().build();

        HttpResponse httpResponse = httpClient.send(httpRequest, HttpResponse.BodyHandler.asString());

        System.out.println("httpResponse body: " + httpResponse.body());
        System.out.println("httpResponse body: " + httpResponse.statusCode());
    }
}

В результате работы программы мы получим, примерно, следующий результат:


WARNING: Using incubator modules: jdk.incubator.httpclient
httpClient version: HTTP_2
httpResponse body: <!doctype html><html itemscope="" itemtype="http://schema.org/WebPage" lang="uk"><head><meta content="text/html; charset=UTF-8" http-equiv="Content-Type"><meta content="/images/branding/googleg/1x/googleg_standard_color_128dp.png" itemprop="image"><title>Google</title><script nonce="cntDbKX86Tdp5AAyZ2XpmQ==">(function(){window.google={kEI:'47A0W-KoNYaYsgHYzrmQBA',kEXPI:'0,201836,1151910,58,1654,303,1018,38,242,495,215,129,260,512,585,154,236,58,313,34,11,134,73,70,204,2339520,205,222,32,329244,1344,12383,2349,2506,32691,15248,867,1568,7,5117,5471,16521,369,548,664,2102,113,1150,1053,3189,725,3,1714,129,131,5107,444,131,1119,2,1306,310,2122,1361,223,1120,369,877,499,505,730,377,1240,479,1295,7,1569,222,552,94,100,395,643,1017,282,2,2710,115,779,459,398,393,132,22,178,426,2,153,273,234,440,1200,121,2,70,3,540,397,3,391,26,230,45,31,866,509,1328,259,296,1344,203,476,15,168,17,43,19,69,109,336,121,7,286,39,24,552,73,143,122,105,386,8,806,96,182,7,30,25,167,269,620,29,386,71,1,211,36,189,4,4,4,4,118,419,406,63,78,1242,394,175,2328128,3685997,13,2541,5997640,2800146,4,1572,549,332,445,1,2,1,1,77,1,1,900,207,1,1,1,1,1,371,9,304,1,8,1,2,1,1,1523,8,7,62,1,25,4,10,26,1,1,1,63,31,1,1,1,19,11,19,3,6,22,1,6,9,2',authuser:0,kscs:'c9c918f0_47A0W-KoNYaYsgHYzrmQBA',kGL:'UA'};google.kHL='uk';})();google.time=function(){return(new Date).getTime()};(function(){google.lc=[];google.li=0;google.getEI=function(a){for(var b;a&&(!a.getAttribute||!(b=a.getAttribute("eid")));)a=a.parentNode;return b||google.kEI};google.getLEI=function(a){for(var b=null;a&&(!a.getAttribute||!(b=a.getAttribute("leid")));)a=a.parentNode;return b};google.https=function(){return"https:"==window.location.protocol};google.ml=function(){return null};google.wl=function(a,b){try{google.ml(Error(a),!1,b)}catch(d){}};google.log=function(a,b,d,c,g){if(a=google.logUrl(a,b,d,c,g)){b=new Image;var e=google.lc,f=google.li;e[f]=b;b.onerror=b.onload=b.onabort=function(){delete e[f]};google.vel&&google.vel.lu&&google.vel.lu(a);b.src=a;google.li=f+1}};google.logUrl=function(a,b,d,c,g){var e="",f=google.ls||"";d||-1!=b.search("&ei=")||(e="&ei="+google.getEI(c),-1==b.search("&lei=")&&(c=google.getLEI(c))&&(e+="&lei="+c));c="";!d&&google.cshid&&-1==b.search("&cshid=")&&"slh"!=a&&(c="&cshid="+google.cshid);a=d||"/"+(g||"gen_204")+"?atyp=i&ct="+a+"&cad="+b+e+f+"&zx="+google.time()+c;/^http:/i.test(a)&&google.https()&&(google.ml(Error("a"),!1,{src:a,glmm:1}),a="");return a};}).call(this);(function(){google.y={};google.x=function(a,b){if(a)var c=a.id;else{do c=Math.random();while(google.y[c])}google.y[c]=[a,b];return!1};google.lm=[];google.plm=function(a){google.lm.push.apply(google.lm,a)};google.lq=[];google.load=function(a,b,c){google.lq.push([[a],b,c])};google.loadAll=function(a,b){google.lq.push([a,b])};}).call(this);google.f={};var a=window.location,b=a.href.indexOf("#");if(0<=b){var c=a.href.substring(b+1);/(^|&)q=/.test(c)&&-1==c.indexOf("#")&&a.replace("/search?"+c.replace(/(^|&)fp=[^&]*/g,"")+"&cad=h")};</script><style>#gbar,#guser{font-size:13px;padding-top:1px !important;}#gbar{height:22px}#guser{padding-bottom:7px !important;text-align:right}.gbh,.gbd{border-top:1px solid #c9d7f1;font-size:1px}.gbh{height:0;position:absolute;top:24px;width:100%}@media all{.gb1{height:22px;margin-right:.5em;vertical-align:top}#gbar{float:left}}a.gb1,a.gb4{text-decoration:underline !important}a.gb1,a.gb4{color:#00c !important}.gbi .gb4{color:#dd8e27 !important}.gbf .gb4{color:#900 !important}
</style><style>body,td,a,p,.h{font-family:arial,sans-serif}body{margin:0;overflow-y:scroll}#gog{padding:3px 8px 0}td{line-height:.8em}.gac_m td{line-height:17px}form{margin-bottom:20px}.h{color:#36c}.q{color:#00c}.ts td{padding:0}.ts{border-collapse:collapse}em{font-weight:bold;font-style:normal}.lst{height:25px;width:496px}.gsfi,.lst{font:18px arial,sans-serif}.gsfs{font:17px arial,sans-serif}.ds{display:inline-box;display:inline-block;margin:3px 0 4px;margin-left:4px}input{font-family:inherit}a.gb1,a.gb2,a.gb3,a.gb4{color:#11c !important}body{background:#fff;color:black}a{color:#11c;text-decoration:none}a:hover,a:active{text-decoration:underline}.fl a{color:#36c}a:visited{color:#551a8b}a.gb1,a.gb4{text-decoration:underline}a.gb3:hover{text-decoration:none}#ghead a.gb2:hover{color:#fff !important}.sblc{padding-top:5px}.sblc a{display:block;margin:2px 0;margin-left:13px;font-size:11px}.lsbb{background:#eee;border:solid 1px;border-color:#ccc #999 #999 #ccc;height:30px}.lsbb{display:block}.ftl,#fll a{display:inline-block;margin:0 12px}.lsb{background:url(/images/nav_logo229.png) 0 -261px repeat-x;border:none;color:#000;cursor:pointer;height:30px;margin:0;outline:0;font:15px arial,sans-serif;vertical-align:top}.lsb:active{background:#ccc}.lst:focus{outline:none}.tiah{width:458px}</style><script nonce="cntDbKX86Tdp5AAyZ2XpmQ=="></script><link href="/images/branding/product/ico/googleg_lodp.ico" rel="shortcut icon"></head><body bgcolor="#fff"><script nonce="cntDbKX86Tdp5AAyZ2XpmQ==">(function(){var src='/images/nav_logo229.png';var iesg=false;document.body.onload = function(){window.n && window.n();if (document.images){new Image().src=src;}
if (!iesg){document.f&&document.f.q.focus();document.gbqf&&document.gbqf.q.focus();}
}
})();</script><div id="mngb"> <div id=gbar><nobr><b class=gb1>&#1055;&#1086;&#1096;&#1091;&#1082;</b> <a class=gb1 href="https://www.google.com.ua/imghp?hl=uk&tab=wi">&#1047;&#1086;&#1073;&#1088;&#1072;&#1078;&#1077;&#1085;&#1085;&#1103;</a> <a class=gb1 href="https://maps.google.com.ua/maps?hl=uk&tab=wl">&#1050;&#1072;&#1088;&#1090;&#1080;</a> <a class=gb1 href="https://www.youtube.com/?gl=UA&tab=w1">YouTube</a> <a class=gb1 href="https://news.google.com.ua/nwshp?hl=uk&tab=wn">&#1053;&#1086;&#1074;&#1080;&#1085;&#1080;</a> <a class=gb1 href="https://mail.google.com/mail/?tab=wm">Gmail</a> <a class=gb1 href="https://drive.google.com/?tab=wo">&#1044;&#1080;&#1089;&#1082;</a> <a class=gb1 href="https://www.google.com/calendar?tab=wc">&#1050;&#1072;&#1083;&#1077;&#1085;&#1076;&#1072;&#1088;</a> <a class=gb1 style="text-decoration:none" href="https://www.google.com.ua/intl/uk/options/"><u>&#1041;&#1110;&#1083;&#1100;&#1096;&#1077;</u> &raquo;</a></nobr></div><div id=guser width=100%><nobr><span id=gbn class=gbi></span><span id=gbf class=gbf></span><span id=gbe></span><a href="http://www.google.com.ua/history/optout?hl=uk" class=gb4>&#1030;&#1089;&#1090;&#1086;&#1088;&#1110;&#1103; &#1074;&#1077;&#1073;-&#1087;&#1086;&#1096;&#1091;&#1082;&#1091;</a> | <a href="/preferences?hl=uk" class=gb4>&#1053;&#1072;&#1083;&#1072;&#1096;&#1090;&#1091;&#1074;&#1072;&#1085;&#1085;&#1103;</a> | <a target=_top id=gb_70 href="https://accounts.google.com/ServiceLogin?hl=uk&passive=true&continue=https://www.google.com/" class=gb4>&#1059;&#1074;&#1110;&#1081;&#1090;&#1080;</a></nobr></div><div class=gbh style=left:0></div><div class=gbh style=right:0></div> </div><center><br clear="all" id="lgpd"><div id="lga"><img alt="Google" height="92" src="/images/branding/googlelogo/1x/googlelogo_white_background_color_272x92dp.png" style="padding:28px 0 14px" width="272" id="hplogo" onload="window.lol&&lol()"><br><br></div><form action="/search" name="f"><table cellpadding="0" cellspacing="0"><tr valign="top"><td width="25%">&nbsp;</td><td align="center" nowrap=""><input name="ie" value="ISO-8859-1" type="hidden"><input value="uk" name="hl" type="hidden"><input name="source" type="hidden" value="hp"><input name="biw" type="hidden"><input name="bih" type="hidden"><div class="ds" style="height:32px;margin:4px 0"><div style="position:relative;zoom:1"><input style="color:#000;margin:0;padding:5px 8px 0 6px;vertical-align:top;padding-right:38px" autocomplete="off" class="lst tiah" value="" title="&#1055;&#1086;&#1096;&#1091;&#1082; Google" maxlength="2048" name="q" size="57"><img src="/textinputassistant/tia.png" style="position:absolute;cursor:pointer;right:5px;top:4px;z-index:300" onclick="(function(){var src='/textinputassistant/11/uk_tia.js';var s=document.createElement('script');s.src=src;(document.getElementById('xjsc')||document.body).appendChild(s);})();" alt="" height="23" width="27"></div></div><br style="line-height:0"><span class="ds"><span class="lsbb"><input class="lsb" value="&#1055;&#1086;&#1096;&#1091;&#1082; Google" name="btnG" type="submit"></span></span><span class="ds"><span class="lsbb"><input class="lsb" value="&#1052;&#1077;&#1085;&#1110; &#1087;&#1086;&#1097;&#1072;&#1089;&#1090;&#1080;&#1090;&#1100;" name="btnI" onclick="if(this.form.q.value)this.checked=1; else top.location='/doodles/'" type="submit"></span></span></td><td class="fl sblc" align="left" nowrap="" width="25%"><a href="/advanced_search?hl=uk&amp;authuser=0">&#1056;&#1086;&#1079;&#1096;&#1080;&#1088;&#1077;&#1085;&#1080;&#1081; &#1087;&#1086;&#1096;&#1091;&#1082;</a><a href="/language_tools?hl=uk&amp;authuser=0">&#1052;&#1086;&#1074;&#1085;&#1110; &#1110;&#1085;&#1089;&#1090;&#1088;&#1091;&#1084;&#1077;&#1085;&#1090;&#1080;</a></td></tr></table><input id="gbv" name="gbv" type="hidden" value="1"></form><div id="gac_scont"></div><div style="font-size:83%;min-height:3.5em"><br><div id="gws-output-pages-elements-homepage_additional_languages__als"><style>#gws-output-pages-elements-homepage_additional_languages__als{font-size:small;margin-bottom:24px}#SIvCob{display:inline-block;line-height:28px;}#SIvCob a{padding:0 3px;}.H6sW5{display:inline-block;margin:0 2px;white-space:nowrap}.z4hgWe{display:inline-block;margin:0 2px}</style><div id="SIvCob">&#1052;&#1086;&#1074;&#1072; Google: <a href="https://www.google.com/setprefs?sig=0_ZjFG2NmR6ryEnZtH_1yxk2sYIzE%3D&amp;hl=ru&amp;source=homepage&amp;sa=X&amp;ved=0ahUKEwiipoSBjPbbAhUGjCwKHVhnDkIQ2ZgBCAU">&#1088;&#1091;&#1089;&#1089;&#1082;&#1080;&#1081;</a> </div></div></div><span id="footer"><div style="font-size:10pt"><div style="margin:19px auto;text-align:center" id="fll"><a href="http://www.google.com.ua/intl/uk/ads/">&#1056;&#1077;&#1082;&#1083;&#1072;&#1084;&#1072;</a><a href="http://www.google.com.ua/intl/uk/services/">&#1056;&#1110;&#1096;&#1077;&#1085;&#1085;&#1103; &#1076;&#1083;&#1103; &#1073;&#1110;&#1079;&#1085;&#1077;&#1089;&#1091;</a><a href="/intl/uk/about.html">&#1059;&#1089;&#1077; &#1087;&#1088;&#1086; Google</a><a href="https://www.google.com/setprefdomain?prefdom=UA&amp;prev=https://www.google.com.ua/&amp;sig=__kIDlXTSh-KxanPhugqw8_ds0dQk%3D">Google.com.ua</a></div></div><p style="color:#767676;font-size:8pt">&copy; 2018</p></span></center><script nonce="cntDbKX86Tdp5AAyZ2XpmQ==">(function(){window.google.cdo={height:0,width:0};(function(){var a=window.innerWidth,b=window.innerHeight;if(!a||!b){var c=window.document,d="CSS1Compat"==c.compatMode?c.documentElement:c.body;a=d.clientWidth;b=d.clientHeight}a&&b&&(a!=google.cdo.width||b!=google.cdo.height)&&google.log("","","/client_204?&atyp=i&biw="+a+"&bih="+b+"&ei="+google.kEI);}).call(this);})();</script><div id="xjsd"></div><div id="xjsi"><script nonce="cntDbKX86Tdp5AAyZ2XpmQ==">(function(){function c(b){window.setTimeout(function(){var a=document.createElement("script");a.src=b;google.timers&&google.timers.load.t&&google.tick&&google.tick("load",{gen204:"xjsls",clearcut:31});document.getElementById("xjsd").appendChild(a)},0)}google.dljp=function(b,a){google.xjsu=b;c(a)};google.dlj=c;}).call(this);if(!google.xjs){window._=window._||{};window._DumpException=window._._DumpException=function(e){throw e};window._F_installCss=window._._F_installCss=function(c){};google.dljp('/xjs/_/js/k\x3dxjs.hp.en.hFhMSvo1KiI.O/m\x3dsb_he,d/am\x3dVGFs/rt\x3dj/d\x3d1/rs\x3dACT90oHc1vZS9qCuNv6T772cR-Fnn34nwA','/xjs/_/js/k\x3dxjs.hp.en.hFhMSvo1KiI.O/m\x3dsb_he,d/am\x3dVGFs/rt\x3dj/d\x3d1/rs\x3dACT90oHc1vZS9qCuNv6T772cR-Fnn34nwA');google.xjs=1;}google.pmc={"sb_he":{"agen":true,"cgen":true,"client":"heirloom-hp","dh":true,"dhqt":true,"ds":"","ffql":"en","fl":true,"host":"google.com","isbh":28,"jsonp":true,"msgs":{"cibl":"&#1054;&#1095;&#1080;&#1089;&#1090;&#1080;&#1090;&#1080; &#1087;&#1086;&#1096;&#1091;&#1082;&#1086;&#1074;&#1080;&#1081; &#1079;&#1072;&#1087;&#1080;&#1090;","dym":"&#1052;&#1086;&#1078;&#1083;&#1080;&#1074;&#1086;, &#1074;&#1080; &#1084;&#1072;&#1083;&#1080; &#1085;&#1072; &#1091;&#1074;&#1072;&#1079;&#1110;:","lcky":"&#1052;&#1077;&#1085;&#1110; &#1087;&#1086;&#1097;&#1072;&#1089;&#1090;&#1080;&#1090;&#1100;","lml":"&#1044;&#1086;&#1082;&#1083;&#1072;&#1076;&#1085;&#1110;&#1096;&#1077;","oskt":"&#1058;&#1088;&#1072;&#1085;&#1089;&#1083;&#1110;&#1090;&#1077;&#1088;&#1072;&#1094;&#1110;&#1103;","psrc":"&#1062;&#1077;&#1081; &#1087;&#1086;&#1096;&#1091;&#1082; &#1074;&#1080;&#1076;&#1072;&#1083;&#1077;&#1085;&#1086; &#1079; &#1074;&#1072;&#1096;&#1086;&#1111; \u003Ca href=\"/history\"\u003E&#1074;&#1077;&#1073;-&#1110;&#1089;&#1090;&#1086;&#1088;&#1110;&#1111;\u003C/a\u003E","psrl":"&#1042;&#1080;&#1076;&#1072;&#1083;&#1080;&#1090;&#1080;","sbit":"&#1055;&#1086;&#1096;&#1091;&#1082; &#1079;&#1072; &#1079;&#1086;&#1073;&#1088;&#1072;&#1078;&#1077;&#1085;&#1085;&#1103;&#1084;","srch":"&#1055;&#1086;&#1096;&#1091;&#1082; Google"},"nds":true,"ovr":{},"pq":"","refpd":true,"rfs":[],"sbpl":24,"sbpr":24,"scd":10,"sce":5,"stok":"JrzDeWTHXANy_dpVz-l74cIWZYs"},"d":{},"ZI/YVQ":{},"Qnk92g":{},"U5B21g":{},"DPBNMg":{},"YFCs/g":{}};google.x(null,function(){});(function(){var r=[];google.plm(r);})();(function(){var m=[]
;google.jsc && google.jsc.m(m);})();</script></div></body></html>
httpResponse body: 200 

Кроме того, мы имеем возможность работать с асинхронными запросами:


package net.proselyte.java9;

import jdk.incubator.http.HttpClient;
import jdk.incubator.http.HttpRequest;
import jdk.incubator.http.HttpResponse;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

public class Http2DemoAsync {
    public static void main(String[] args) throws URISyntaxException, InterruptedException, ExecutionException {
        HttpClient httpClient = HttpClient.newHttpClient();
        System.out.println("httpClient version: " + httpClient.version());

        HttpRequest httpRequest = HttpRequest.newBuilder().uri(new URI("https://www.google.com/")).GET().build();

        CompletableFuture<HttpResponse> httpResponse = httpClient.sendAsync(httpRequest, HttpResponse.BodyHandler.asString());

        if (httpResponse.isDone()) {
            System.out.println("httpResponse body: " + httpResponse.get().body());
            System.out.println("httpResponse body: " + httpResponse.get().statusCode());
        }else {
            System.out.println("Response is not completed...");
            httpResponse.cancel(true);
        }
    }
}

В результате выполнения данного примера, мы получим:


WARNING: Using incubator modules: jdk.incubator.httpclient
httpClient version: HTTP_2
Response is not completed...

На этом мы заканчиваем обор поддержки HTTP 2 в Java 9 и цикл в целом.