首页 » 漏洞 » 用IntelliJ和Gradle体验JDK9的新HTTP客户端模块

用IntelliJ和Gradle体验JDK9的新HTTP客户端模块

 

多年来,JDK内置的HTTP客户端,也就是 HttpURLConnection ,从没有得到过更新,已经非常老旧,只支持HTTP/1.1、不支持NIO不说,用起来也很麻烦。所以,很多人会使用第三方的HTTP客户端库,比如Apache HttpClient,或是基于Netty的Async Http Client。为了跟上时代,JDK9新增了jdk.incubator.httpclient模块,提供了一个支持HTTP2,WebSocket和Async的HTTP客户端。下载JDK9之后,我第一时间体验了这个新客户端,在这里简单介绍一下,并且记录一下遇到的一些坑。

// 建立Gradle工程

首先,在IntelliJ的向导中创建一个工程。当然了,不是IntelliJ IDEA工程。我习惯用构建工具来管理工程,这样不用IntelliJ的人也能轻松导入。在构建工具中,我比较喜欢Gradle,因为它需要写的字符数比较少。要注意的是,JDK要选择JDK9,而Gradle Distribution选择使用Gradle Wrapper提供的。

创建工程之后,修改 gradle/gradle-wrapper.properties 里面的Gradle下载链接,替换为最新版的链接;或者也可以运行例如

./gradlew wrapper --gradle-version=4.2.1 --distribution-type=bin

来将Wrapper引用的Gradle版本更新为最新。

然后,修改 build.gradle ,将 sourceCompatibility 改成1.9。

// 试用新HTTP客户端API

新的HTTP客户端API主要由三个类组成—— HttpClientHttpRequestHttpResponse 。下面就写一个简单的小程序来尝试一下。

package io.dante.jdk9.http;  import jdk.incubator.http.HttpClient; import jdk.incubator.http.HttpRequest; import jdk.incubator.http.HttpResponse;  import java.net.URI; import java.nio.charset.Charset; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ScheduledThreadPoolExecutor;  public class JDK9HttpClient {   public static void main(String[] args) {   new JDK9HttpClient().get();  }   public JDK9HttpClient() {   _executor = new ScheduledThreadPoolExecutor(5);    _httpClient = HttpClient.newBuilder()    .version(HttpClient.Version.HTTP_1_1)    .executor(_executor)    .build();  }   public void get() {   HttpRequest httpRequest = HttpRequest.newBuilder()    .GET()    .uri(URI.create("https://www.baidu.com"))    .build();    CompletableFuture<HttpResponse<String>> f = _httpClient.sendAsync(    httpRequest, HttpResponse.BodyHandler.asString(Charset.defaultCharset()));    f.thenAcceptAsync(    response -> {     System.out.println(response.body());    },    _executor);  }   private final ScheduledThreadPoolExecutor _executor;  private final HttpClient _httpClient;  }

这个程序只是用来展示一下新的API,写得非常简略,线程池都没有正确退出。可以看到,JDK9 HTTP客户端的API与以前的截然不同, HttpClientHttpRequest 的实例使用Builder模式来创建,写起来更加直观和流畅;提供了异步方法来发送请求,配合 CompletableFuture 可以编写比较复杂的异步程序。当然,还有很多新特性,在这段程序中并没有列出。比如, HttpRequest.BodyProcessor 是一个 Flow.Publisher ,而 HttpResponse.BodyProcessor 则是一个 Flow.Subcriber ,而 Flow 正是Java 9新增的Reactive编程框架。总之,新的HTTP客户端,不但在API设计上向流行的第三方客户端靠拢,还与其他Java 8和9中的新API深度集成,应该能够在很多时候替代第三方客户端。

// 编译和运行

如果直接尝试用Gradle编译工程,就会在编译上面的类的时候失败。Gradle给出的编译错误是,使用了模块里的类,但是模块并不在模块图中。前面只是在代码中导入了httpclient模块中的类,但是模块化的一个特点就是,要声明自己所用到的模块。这里,我们需要进行一些修改,才能让Gradle正确地编译和运行依赖于JDK9模块的程序。

首先,IntelliJ已经提供了对JDK9模块描述文件的支持。在root包下右键添加一个 module-info.java 之后,IntelliJ就会自动在代码编辑器中给出错误提示,并给出自动修复选项。实际上,就是在描述文件中,添加一行 requires 来声明对模块的依赖:

module JDK9.Play {  requires jdk.incubator.httpclient; }

这样一来,JDK就能够正确处理模块依赖关系了。

接下来是Gradle。最新版的Gradle并没有内置对JDK9模块的支持,但是可以通过一些“hack”来解决。一种方法是去为相应的task附加代码,可以参考 Building Java 9 Modules 里面的长篇大论;另一种方法则是直接这个教程的最下方,使用最后一章介绍的 experimental-jigsaw 插件。这里我选择后者。将插件添加到 build.gradle 之后,就可以编译成功了。

// In the end

虽然新HTTP客户端模块的名字 jdk.incubator.httpclient 告诉我们这还是个实验性功能,但据说在下一个大版本中,就会有名为 java.httpclient 的正式版模块了。希望这一天早些到来。

原文链接:用IntelliJ和Gradle体验JDK9的新HTTP客户端模块,转载请注明来源!

0