范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

Java11新特性效能翻倍的HttpClient

  古老的背景
  从JDK1.1开始,JDK中就有HttpURLConnection来提供了网络连接的能力,但是由于实现的比较古早,其有很多的局限性。比如HttpURLConnection是通过底层提供的socket连接来进行通信,而每一个HttpURLConnection实例只能发送一个请求,之后只能通过close()释放请求的网络资源,或在持久化连接时用disconnect()来关闭关闭底层socket。而其基类URLConnection是为了支持很多协议而设计的,但诸如FTP这种协议已经不咋用了。
  HttpURLConnection并不是不能使用,由于不需要依赖,在一些demo项目的时候也会偶尔拿来用。但HttpURLConnection本身已经太过古早,并且很难说HttpURLConnection能够胜任包含各种鉴权信息、各种COOKIE信息的访问请求。
  针对这种情况网络上各种大神提供了更多高级的封装,比较流行的有Apache的HttpClient、Okhttp Client、Spring Cloud Feign之类的。这些封装提供了更丰富的资源与更便捷的封装,也支持了更高级功能如HTTP/2协议、异步请求等。
  不过到了JDK9的时候,Java提供了一个新的Http请求工具HttpClient,经过了JDK10的再次预览,最终在JAVA11中作为正式功能提供使用,同时也完全替换了仅有阻塞模式的HttpURLConnection。 HttpClient简介
  作为JDK11中正式推出的新Http连接器,支持的功能还是比较新的,主要的特性有: 完整支持HTTP 2.0 或者HTTP 1.1 支持 HTTPS/TLS 有简单的阻塞使用方法 支持异步发送,异步时间通知 支持WebSocket 支持响应式流
  HTTP2.0其他的客户端也能支持,而HttpClient使用CompletableFuture作为异步的返回数据。WebSocket的支持则是HttpClient的优势。响应式流的支持是HttpClient的一大优势。
  而HttpClient中的NIO模型、函数式编程、CompletableFuture异步回调、响应式流让HttpClient拥有极强的并发处理能力,所以其性能极高,而内存占用则更少。
  HttpClient的主要类有: java.net.http.HttpClient java.net.http.HttpRequest java.net.http.HttpResponse java.net.http.WebSocket(本文就不介绍这个了)
  细节会在后文介绍,但是WebSocket用的比较少,本文就略过了。 核心使用
  HttpClient 的核心类主要就是 HttpClient、HttpRequest以及HttpResponse,它们都是位于java.net.http 包下,接下来对他们进行一下介绍。 HttpClient
  HttpClient类是最核心的类,它支持使用建造者模式进行复杂对象的构建,主要的参数有: Http 协议的版本 (HTTP 1.1 或者 HTTP 2.0),默认是 2.0。 是否遵从服务器发出的重定向 连接超时时间 代理 认证 //可以用参数调整 HttpClient client = HttpClient.newBuilder()                          .version(Version.HTTP_1_1)                          .followRedirects(Redirect.NORMAL)                          .connectTimeout(Duration.ofSeconds(20))                          .proxy(ProxySelector.of(new InetSocketAddress("proxy.example.com", 8080)))                          .authenticator(Authenticator.getDefault())                          .build();                           //也可以直接全部默认的便捷创建 HttpClient clientSimple = HttpClient.newHttpClient();
  当创建了HttpClient实例后,可以通过其发送多条请求,不用重复创建。 HttpRequest
  HttpRequest 是用语描述请求体的类,也支持通过建造者模式构建复杂对象,主要的参数有: 请求地址 请求方法:GET,POST,DELETE 等(默认是GET) 请求体 (按需设置,例如 GET 不用 body,但是 POST 要设置) 请求超时时间(默认) 请求头 //使用参数组合进行对象构建,读取文件作为请求体 HttpRequest request = HttpRequest.newBuilder()                 .uri(URI.create("http://www.baidu.com"))                 .timeout(Duration.ofSeconds(20))                 .header("Content-type","application/json")                 .POST(HttpRequest.BodyPublishers.ofFile(Paths.get("data.json")))                 .build(); //直接GET访问 HttpRequest requestSimple = HttpRequest.newBuilder(URI.create("http://www.baidu.com")).build();
  HttpRequest 是一个不可变类,可以被多次发送。 HttpResponse
  HttpResponse没有提供外部可以创建的实现类,它是一个接口,从client的返回值中创建获得。接口中的主要方法为: public interface HttpResponse {         public int statusCode();         public HttpRequest request();         public Optional> previousResponse();         public HttpHeaders headers();         public T body();         public URI uri();         public Optional sslSession();         public HttpClient.Version version();     }
  HttpResponse的返回内容与常识一致,这里就不展开介绍了。 信息发送
  HttpClient中可以使用同步发送或者异步发送。
  同步 send()
  同步发送后,请求会一直阻塞到收到response为止。 final HttpResponse send = client.send(httpRequest, HttpResponse.BodyHandlers.ofString()); System.out.println(send.body());
  其中 send的第二个参数是通过HttpResponse.BodyHandlers的静态工厂来返回一个可以将 response 转换为目标类型T的处理器(handler),本例子中的类型是String。HttpResponse.BodyHandlers.ofString()的实现方法为: public static BodyHandler ofString() {             return (responseInfo) -> BodySubscribers.ofString(charsetFrom(responseInfo.headers())); }
  其中,BodySubscribers.ofString() 的方法实现是: public static BodySubscriber ofString(Charset charset) {     Objects.requireNonNull(charset);     return new ResponseSubscribers.ByteArraySubscriber<>(            bytes -> new String(bytes, charset)     ); }
  可以看到最终是返回了一个ResponseSubscribers ,而Subscribers则是我们之前《JDK9响应式编程》中讨论过的订阅者。这个构造方法的入参Function定义了订阅者中的finisher属性,而这个属性将在响应式流完成订阅的时在onComplete()`方法中调用。
  异步 sendAsync()
  异步请求发送之后,会立刻返回 CompletableFuture,然后可以使用CompletableFuture中的方法来设置异步处理器。 client.sendAsync(httpRequest, HttpResponse.BodyHandlers.ofString())         .thenApply(HttpResponse::body)         .thenAccept(System.out::println)         .join();
  而就如同JDK中响应式流中发布者的submit()方法与offer()方法一样,HttpClient中的send()方法知识sendAsync方法的特例,在send()方法中是先调用sendAsync()方法,然后直接阻塞等待响应结束再返回,部分核心代码为:     @Override     public  HttpResponse     send(HttpRequest req, BodyHandler responseHandler)         throws IOException, InterruptedException     {         CompletableFuture> cf = null;          // if the thread is already interrupted no need to go further.         // cf.get() would throw anyway.         if (Thread.interrupted()) throw new InterruptedException();         try {             cf = sendAsync(req, responseHandler, null, null);             return cf.get();         } catch (InterruptedException ie) {             if (cf != null )                 cf.cancel(true);             throw ie;         }       ...
  响应式流
  HttpClient 作为 Request 的发布者 (publisher),将 Request 发布到服务器,作为 Response 的订阅者 (subscriber),从服务器接收 Response。而上文中我们在send()的部分发现,调用链的最底端返回的是一个ResponseSubscribers订阅者。
  当然,就如同HttpResponse.BodyHandlers.ofString(),HttpClient默认提供了一系列的默认订阅者,用语处理数据的转换: HttpRequest.BodyPublishers::ofByteArray(byte[]) HttpRequest.BodyPublishers::ofByteArrays(Iterable) HttpRequest.BodyPublishers::ofFile(Path) HttpRequest.BodyPublishers::ofString(String) HttpRequest.BodyPublishers::ofInputStream(Supplier)  HttpResponse.BodyHandlers::ofByteArray() HttpResponse.BodyHandlers::ofString() HttpResponse.BodyHandlers::ofFile(Path) HttpResponse.BodyHandlers::discarding()
  所以在HttpClient的时候我们也可以自己创建一个实现了Flow.Subscriber>接口的订阅者,用于消费数据。响应式流完整的简单的例子如下: public class HttpClientTest {      public static void main(String[] args) throws IOException, InterruptedException {         final HttpClient client = HttpClient.newHttpClient();         final HttpRequest httpRequest = HttpRequest.newBuilder(URI.create("http://www.baidu.com")).build();          HttpResponse.BodySubscriber subscriber = HttpResponse.BodySubscribers.fromSubscriber(new StringSubscriber(),StringSubscriber::getBody);         client.sendAsync(httpRequest,responseInfo -> subscriber)                 .thenApply(HttpResponse::body)                 .thenAccept(System.out::println)                 .join();     }      static class StringSubscriber implements Flow.Subscriber>{         Flow.Subscription subscription;         List response = new ArrayList<>();         String body;         public String getBody(){             return body;         }          @Override         public void onSubscribe(Flow.Subscription subscription) {             this.subscription = subscription;             subscription.request(1);         }          @Override         public void onNext(List item) {             response.addAll(item);             subscription.request(1);         }          @Override         public void onError(Throwable throwable) {             System.err.println(throwable);         }          @Override         public void onComplete() {             byte[] data = new byte[response.stream().mapToInt(ByteBuffer::remaining).sum()];             int offset = 0;             for(ByteBuffer buffer:response){                 int remain = buffer.remaining();                 buffer.get(data,offset,remain);                 offset += remain;             }             body = new String(data);         }     } }最后
  HttpClient是JDK11正式上线的高性能Http客户端。其底层基于响应式流,通过上层封装还提供了异步信息发送、同步信息发送,以及其他完成的HTTP协议内容。在进行响应式编程的方面,HttpClient也是一个十分优秀的参照目标。

win7设备管理器空白的解决方法相信深度技术的电脑老用户都知道,win7系统中的设备管理器可以查看系统中设备是否全部能够正常运行,但有小伙伴说他的电脑设备管理器一打开就显示一片空白的问题。下面,深度系统小编整理了win7系统电脑微信的多开设置方法相信很多深度技术的用户,都会使用到微信电脑版,但是有的小伙伴因为工作原因不止一个微信账户,我们都知道在安卓手机上可以实现多开微信。那小伙伴就想在win764位纯净版系统里面实现微信windows10正式版设置虚拟内存的方法很多深度技术的小伙伴都可能不知道,当我们使用的windows10正式版系统电脑内存不够用时,可以通过设置一下虚拟内存就可以有效地提高系统的性能,缓解内存压力了。但是设置虚拟内存有一win10系统出现xbox无法登陆的处理方法很多深度技术的小伙伴都知道,Xbox是win10系统中自带的游戏平台,全称XboxGameBAR。喜欢玩游戏的小伙伴可以在xbox应用商店下载自己感兴趣的游戏到本地。但有深度win深度技术解决win7玩游戏无法全屏的处理方法一些深度技术之家的小伙伴在使用win764旗舰版电脑玩游戏的时候出现无法全屏的问题。出现这种情况非常影响我们的游戏体验感,但该如何解决呢?下面深度系统之家小编就来分享一下具体的解决深度技术分享windows7激活的方法和不激活的结果有不少深度技术的用户,在电脑安装了Win7系统之后,一般都是自动激活的,但是也会遇到win7系统不激活的问题。有的小伙伴就问了,如果win7不激活会有什么事情发生呢?当然,如果不激打造完美的家庭环境,你需要这些舒适的家居好物前言大家好,我是小猴。由于各地的疫情原因,大部分人都会在家居家隔离。因此每天呆在家里的时间也会比以往正常上班时多了很多。许多值友每天不仅开启了一日三餐的下厨生活,更多的时间也会花在米家加湿器选购指南前言大家好,我是小猴。之前为大家带来了几篇冬季空气类家电的使用指南以及加湿器的使用注意事项,有不少小伙伴就询问购买加湿器的问题。因此,接下来为大家带来几篇不同品牌加湿器的选购指南文百元音箱不智障,小度智能音箱青春版也能玩转智能家居前言大家好,我是小猴。随着智能家居的普及,每个人的家里或多或少都会有了一些智能家电。而控制这些智能家电的重要智能终端又以智能音箱为主,目前主要有小米的小爱音箱系列,苹果的homep智能家居的重要拼图,没有手机一样玩转米家之红米8寸大屏幕音箱前言大家好,我是小猴。智能家居的核心是什么?路由器还是无线网关,恐怕对于普通人来说也是个搞不清的问题。然而最直接的感受就是,目前智能家居系统接入的方式主要还是通过形形色色的智能音箱买闹钟送温湿度传感器,青萍蓝牙闹钟开箱前言大家好,我是小猴。春暖花开的季节,每天早晨起床绝对是一件十分困难的事情。尽管每天睡前都会检查一下自己的手机闹钟是否打开,每天早晨依然偶尔会睡过头迟到。记得上学的时候,闹钟绝对是
比纸还轻,真的好听!GIECCandyPods耳机体验年少不屑影碟机,轻装上阵才自由玩过DVD的人,十有八九接触过老牌厂家杰科(GIEC)。70后亲爹书房光碟一摞摞,用的就是GIEC的影碟机。可惜时光一去不回头,如今我们看片用W盘讯X远程办公不求人,向日葵开机插座测评前几天在网上看到有人用手机或者平板电脑远程控制电脑的文章,看到之后自己心动不已,在经过一系列探查之后发现其实操作并不困难。下载国民远控软件向日葵远程控制就能搞定,有点像之前QQ的远10年家居设计师测评,米家bMOLA空气净化器有何特别关键看这点我们生活中的雾霾沙尘花粉柳絮yi情肆意层出不穷的空气质量问题,导致越来越多家庭选择购买空气净化器。作为一名从业了10年的设计师,在家居家电领域颇有研究,想聊聊米家bMOLA空气净化双屏显示真的爽!北弧E5002双屏显示器支架安装体验双屏显示真的爽,值友诚不我欺!北弧E5002双屏显示器支架安装体验大家好,我是噩梦飘雷关注我,后续分享更多折腾经验前文讲到,最近由于疫情因素,宅家的时间大大增加,想给电脑添加一个显华为笔记本电脑一个月主板坏了3月24购买一台笔记本电脑,4月28日出现阶段性卡顿现象,键盘输入乱码,充电口接触不良等现象,已不能使用,5月2日到华为官方售后检测说需要更换电脑主板,售后给的回复就是只能维修,更恒大汽车遭疯抢?曝预售10小时爆单5万台!网友没找到订车入口5月9日消息,近期有报道称,恒大汽车旗下恒驰品牌近期开启预售,盲订后10小时内订单就达到5万辆。该消息一经曝光就引起了网友的广泛议论,有网友表示,并没有看到有关恒驰5的订车入口,并安森美等暂不接单,车用IGBT芯片短缺严峻芯片短缺于2020年底从汽车行业开始蔓延到涉及半导体的各个领域,而今,一年多过去之后,汽车行业的芯片短缺仍然处于深水区。最近,据财联社报道,安森美深圳工厂内部人士称车用绝缘栅双极晶理想汽车被曝毁约校招生,官方回应因业务调整,提供调岗或赔偿Tech星球5月11日消息,近日有网友在社交平台曝光,称理想汽车毁约校招生,据网友曝光的邮件内容透露,解约原因是由于理想汽车近期对业务架构进行调整,目前公司没有相关匹配的岗位。对此理想汽车回应校招生被拒因业务有调整提供调岗或解约赔偿新京报贝壳财经讯有用户在脉脉等平台透露,理想汽车在5月毁约了2022年毕业的校招生,其中不少人已经和理想汽车学校签署了三方协议,准备等着毕业答辩结束后入职。对此,理想汽车回应称这个js基础面试题221240道题目221。什么是假值对象?参考答案浏览器在某些特定情况下,在常规JavaScript语法基础上自己创建了一些外来值,这些就是假值对象。假值对象看起来和普通对象并无二致(都有属性,等等js基础面试题131160道题目131。用原生JavaScript的实现过什么功能吗?参考答案轮播图手风琴放大镜3D动画效果等,切记,所答的一定要知道实现原理!,不知道还不如不说!参与互动132。javascri