📜  Java 9 的 HTTP/2 客户端特性和示例

📅  最后修改于: 2021-10-31 05:34:21             🧑  作者: Mango

HTTP/2 客户端: HTTP/2 客户端是 JDK 9 的特性之一。HTTP/2 是 HTTP 协议的最新版本。在 HTTP/2 客户端的帮助下,我们可以从Java应用程序发送 HTTP 请求并处理 HTTP 响应。在 JDK 9 之前,为了发送 HTTP 请求并处理 HTTP 响应,我们使用 HttpURLConnection 类。现在你会想知道为什么 JDK 9 中引入了 HTTP/2 客户端,而我们有 HttpURLConnection 来解决这个问题。但是现有的 HttpURLConnection 几乎没有在 HTTP/2 客户端中消除的问题。

HttpURLConnection 的几个主要问题:

  1. HttpURLConnection 类仅支持HTTP/1.1 协议而不支持 HTTP/2.0 协议。协议只不过是用于在电子设备(例如计算机)之间传输数据的一组规则或程序。 HTTP 代表超文本传输协议,这里的协议代表用于在客户端和服务器之间建立通信的数据通信协议。由于 HttpURLConnection 类仅支持 HTTP/1.1,这就是为什么如果我们使用 HttpURLConnection 类,那么每个 TCP 连接只能发送一个请求。这将导致应用程序的网络流量和性能问题。由于 HttpURLConnection 仅支持 HTTP/1.1,它只能处理文本数据,不能处理二进制数据
  2. HttpURLConnection 类仅适用于同步模式。同步模式意味着我们必须等待请求完成其任务才能发送另一个请求。如果我们使用 HttpURLConnection 类来处理 HTTP 请求,那么我们必须保持空闲,直到我们得到请求的响应,然后我们才能处理另一个 HTTP 请求,这会导致性能问题。

HTTP/2.0 客户端的优点:

  1. HTTP/2.0 客户端非常轻量且易于使用。 HTTP/2.0 客户端同时支持HTTP/1.1 和 HTTP/2.0 。 HTTP/2 专注于数据如何在服务器和客户端之间构建和传输。在 HTTP/1.1 中,我们一次不能打开超过 6 个连接,因此每个请求都必须等待其他请求完成。上述问题的解决方案是在 HTTP/2 客户端进行多路复用。这意味着借助 HTTP/2 可以通过单个 TCP 连接并行发送多个 HTTP 请求。
  2. 在 HTTP/1.1 中,当我们发送一个包含标头信息的 HTTP 请求时,HTTP/1.1 将标头数据视为附加数据,从而增加了带宽。这可以在 HTTP/2.0 中通过使用HPack进行标头压缩来消除。
  3. HTTP/2.0 客户端支持文本和二进制数据进行处理。
  4. HTTP/2.0 客户端工作在同步和异步模式。 .与 HttpURLConnection 相比,HTTP/2.0 客户端提供了更好的性能。

Java 9 中的 HTTP API:在Java 9 中引入了一个新的 API,它易于使用并且还增加了对 HTTP/2 的支持。引入了 3 个新类来处理 HTTP 通信。这三个类存在于模块内的jdk.incubator.httpclient模块和jdk.incubator.http包中。由于 jdk.incubator.httpclient 不存在于Java应用程序中,我们必须在 module-info 中显式导入它。 Java文件。

  1. HttpClient: HttpClient 是多个 HttpRequest 共有的配置信息的容器。所有请求都通过 HttpClient 发送。 HttpClients 是不可变的,是从 newBuilder() 返回的构建器创建的。请求构建器是通过调用 HttpRequest.newBuilder() 创建的。
  2. HttpRequest: HttpRequest 代表一个可以发送到服务器的 HTTP 请求。HTTP 请求是从 HttpRequest 构建器构建的。 HttpRequest 构建器是通过调用 HttpRequest.newBuilder 获得的。可以设置请求的 URI、标头和正文。请求主体通过 HttpRequest 提供。提供给 DELETE、POST 或 PUT 方法的 BodyProcessor 对象。 GET 不采取身体。一旦在构建器中设置了所有必需的参数,就会调用 HttpRequest.Builder.build() 以返回 HttpRequest。
  3. HttpResponse:当收到响应状态代码和标头时,并且通常在收到响应正文之后,HttpResponse 可用。

例子:

HTTP/2.0 的虚拟项目:正如我们已经知道在Java 9 中我们不能直接使用内部 API,我们必须在模块描述符文件中创建一个条目。这里使用jdk.incubator.httpclient模块中存在的新 HTTP API。我们不得不在模块描述符文件中提到它。我们必须按照以下步骤在Java 9 上使用 HTTP/2 执行操作:-

  • 首先创建一个名为src的文件夹,即我们Java程序的源文件夹,在那个名为geeks的文件夹中,该文件夹将包含元数据信息,然后在geeks中创建一个名为httpPackage的文件夹,它只是名字我们将在其中放置Java代码的包。
  • 创建模块信息。 Java直接在 geeks 中,如下所示:
    module geeks
    {
        requires jdk.incubator.httpclient;
    }
    
  • 在名为 Geeksforgeeks 的 httpPackage 文件夹中创建Java类。 Java和如下实现:
    package httpPackage;
    import java.io.IOException;
    import java.net.URI;
    import jdk.incubator.http.HttpClient;
    import jdk.incubator.http.HttpRequest;
    import jdk.incubator.http.HttpResponse;
      
    public class Geeksforgeeks {
        public static void main(String[] args)
        {
            try {
                // Create a HttpClient
                HttpClient httpClient
                    = HttpClient.newHttpClient();
      
                // create a HttpRequest object with the URL
                HttpRequest httpRequest
                    = HttpRequest
                          .newBuilder()
                          .uri(new URI("https:// www.geeksforgeeks.org/about/"))
                          .GET()
                          .build();
                // Synchronous send() method
                // to process the HTTP request.
                // HttpResponse.BodyHandler.asString() handles
                // the body of the response as a String.
                HttpResponse httpResponse
                    = httpClient.send(
                        httpRequest,
                        HttpResponse.BodyHandler.asString());
      
                // statusCode() returns the status code
                // for this response.
                System.out.println(
                    "Status of operation performed:"
                    + httpResponse.statusCode());
            }
            catch (Exception e) {
                System.out.println("Exception" + e);
            }
        }
    }
    
  • 要编译我们的Java代码,我们必须转到 src 文件夹并执行以下命令:
    javac --module-source-path src-d-out -m geeks
  • 要运行我们的Java代码,我们必须执行以下命令:
    java --module-path out -m geeks/httpPackage.Geeksforgeeks

    输出:

    WARNING: using incubator modules jdk.incubator.httpclient
    Status of operation performed:200
    
  • 从上面的程序中,我们可以通过同步的 send() 方法发送一个 HTTP GET 请求,并将响应作为字符串处理。假设我们不想等到 HTTP 请求完成并且想要并行发送另一个 HTTP 请求,并且我们想要将响应保存到一个文件中。在上面的例子中,我们使用了同步特性,它会阻塞直到它完成。我们可以使它异步,也可以将响应保存到文件中。
    import java.nio.file.Paths;
    import java.io.IOException;
    import java.net.URI;
    import jdk.incubator.http.HttpClient;
    import jdk.incubator.http.HttpRequest;
    import jdk.incubator.http.HttpResponse;
      
    public class Geeksforgeeks {
        public static void main(String[] args)
        {
            try {
                // Create a HttpClient
                HttpClient httpClient
                    = HttpClient.newHttpClient();
      
                // create a HttpRequest object with the URL
                HttpRequest httpRequest
                    = HttpRequest
                          .newBuilder()
                          .uri(new URI("https:// www.geeksforgeeks.org/about/"))
                          .GET()
                          .build();
      
                // Synchronous send() method
                // to process the HTTP request.
                // HttpResponse.BodyHandler.asFile(Paths.get("GFG.html"))
                // save the response body into GFG.html file
                HttpResponse httpResponse
                    = httpClient.send(
                        httpRequest,
                        HttpResponse.BodyHandler.asFile(Paths.get("GFG.html")));
      
                // statusCode() returns the status code for this response.
                System.out.println(
                    "Status of operation performed:"
                    + httpResponse.statusCode());
      
                // body() returns the response of HTTP request
                System.out.println("Response body:"
                                   + httpResponse.body());
            }
            catch (Exception e) {
                System.out.println("Exception" + e);
            }
        }
    }
    

    输出:

    WARNING: using incubator modules jdk.incubator.httpclient
    Status of operation performed:200
    Response body: It will return the source code of https://www.geeksforgeeks.org/about/ page. As the response is too big i am not adding in it here.