JDK变化
- 从java9的jdk.incubator.httpclient模块迁移到java.net.http模块,包名由jdk.incubator.http改为java.net.http
- 原来的诸如HttpResponse.BodyHandler.asString()方法变更为HttpResponse.BodyHandlers.ofString(),变化一为BodyHandler改为BodyHandlers,变化二为asXXX()之类的方法改为ofXXX(),由as改为of
- 官方文档:https://docs.oracle.com/en/java/javase/11/docs/api/java.net.http/java/net/http/package-summary.html
实例
设置超时时间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
HttpConnectTimeoutException实例
1 2 3 4 5 6 7 |
|
HttpTimeoutException实例
1 2 3 4 5 |
|
设置authenticator
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
- authenticator可以用来设置HTTP authentication,比如Basic authentication
- 虽然Basic authentication也可以自己设置header,不过通过authenticator省得自己去构造header
设置header
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
通过request可以自己设置header,多个header可直接传入可变参数headers(String数组),或者传入传统的Map型的header直接流转换为headers
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
GET
同步
1 2 3 4 5 6 7 8 9 10 11 12 |
|
异步
1 2 3 4 5 6 7 8 9 10 11 |
|
POST表单
1 2 3 4 5 6 7 8 9 10 11 12 |
|
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 |
|
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 |
|
- 官方的HttpClient并没有提供类似WebClient那种现成的BodyInserters.fromMultipartData方法,因此这里需要自己转换
- 这里使用org.apache.httpcomponents(httpclient及httpmime)的MultipartEntityBuilder构建multipartEntity,最后通过HttpRequest.BodyPublishers.ofInputStream来传递内容
- 这里header要指定Content-Type值为multipart/form-data以及boundary的值,否则服务端可能无法解析
文件下载
1 2 3 4 5 6 7 8 9 10 11 |
|
使用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 |
|
- 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 |
|
- 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 |
|
执行之后可以看到返回的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 |
|
- 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 |
|
- BodySubscriber接口继承了Flow.Subscriber<List<ByteBuffer>>接口
- 这里的Subscription来自Flow类,该类是java9引入的,里头包含了支持Reactive Streams的实现
小结
HttpClient在Java11从incubator变为正式版,相对于传统的HttpUrlConnection其提升可不是一点半点,不仅支持异步,也支持reactive streams,同时也支持了HTTP2以及WebSocket,非常值得大家使用。