【问题标题】:Does Apache or some other CLIENT JAVA implementation support HTTP/2?Apache 或其他一些 CLIENT JAVA 实现是否支持 HTTP/2?
【发布时间】:2016-01-16 04:10:45
【问题描述】:

我正在寻找可以连接到基于 HTTP/2 的服务器的 Java 客户端。该服务器已经支持 HTTP/2 API。我看不到最流行的 Apache Http 客户端 https://hc.apache.org/ 仍然支持 HTTP/2。

Apache 是否已经有一些支持 Http/2 的 Java 客户端实现?

如果没有,是否有一些 Java 客户端支持连接到 HTTP/2,最好是在 Java 7 上?

【问题讨论】:

    标签: java apache http httpclient http2


    【解决方案1】:

    Jetty 提供了两个 HTTP/2 Java 客户端 API。两者都需要 Java 8(或更高版本)和强制使用 ALPN,如 here 所述。

    低级 API

    这些 API 基于 HTTP2Client,它基于 sessionstreams 的 HTTP/2 概念,并使用侦听器来通知 HTTP/2 从服务器到达的帧。

        // Setup and start the HTTP2Client.
        HTTP2Client client = new HTTP2Client();
        SslContextFactory sslContextFactory = new SslContextFactory();
        client.addBean(sslContextFactory);
        client.start();
    
        // Connect to the remote host to obtains a Session.
        FuturePromise<Session> sessionPromise = new FuturePromise<>();
        client.connect(sslContextFactory, new InetSocketAddress(host, port), new ServerSessionListener.Adapter(), sessionPromise);
        Session session = sessionPromise.get(5, TimeUnit.SECONDS);
    
        // Use the session to make requests.
        HttpFields requestFields = new HttpFields();
        requestFields.put("User-Agent", client.getClass().getName() + "/" + Jetty.VERSION);
        MetaData.Request metaData = new MetaData.Request("GET", new HttpURI("https://webtide.com/"), HttpVersion.HTTP_2, requestFields);
        HeadersFrame headersFrame = new HeadersFrame(metaData, null, true);
        session.newStream(headersFrame, new Promise.Adapter<>(), new Stream.Listener.Adapter()
        {
            @Override
            public void onHeaders(Stream stream, HeadersFrame frame)
            {
                // Response headers.
                System.err.println(frame);
            }
    
            @Override
            public void onData(Stream stream, DataFrame frame, Callback callback)
            {
                // Response content.
                System.err.println(frame);
                callback.succeeded();
            }
        });
    

    高级 API

    Jetty 的HttpClient 提供了一种使用different transports 的方法,其中之一就是HTTP/2 transport。应用程序将使用更高级别的 HTTP API,但在 Jetty 下将使用 HTTP/2 来传输 HTTP 语义。

    通过这种方式,应用程序可以透明地使用 HttpClient 提供的高级 API,并确定在配置或启动代码中使用什么传输。

        // Setup and start HttpClient with HTTP/2 transport.
        HTTP2Client http2Client = new HTTP2Client();
        SslContextFactory sslContextFactory = new SslContextFactory();
        HttpClient httpClient = new HttpClient(new HttpClientTransportOverHTTP2(http2Client), sslContextFactory);
        httpClient.start();
    
        // Make a request.
        ContentResponse response = httpClient.GET("https://webtide.com/");
    

    【讨论】:

    • Jetty API 没有错误报告...它只是挂起...即使您在上面提供的示例也挂起(高级 API)
    • 我忘了提到 ALPN 要求。我已通过指向 ALPN 文档部分的链接更新了答案。
    • 我终于选择了 netty,因为不需要 ALPN 支持
    【解决方案2】:
    【解决方案3】:

    Jetty 从 9.3 版开始支持 HTTP2。这包括服务器和the client

    【讨论】:

      【解决方案4】:

      Apache httpclient-5 beta 支持 jdk9 或更高版本的 http/2

      例子:

      public static void main(final String[] args) throws Exception {
          final SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(new TrustAllStrategy()).build();
          final PoolingAsyncClientConnectionManager connectionManager = PoolingAsyncClientConnectionManagerBuilder.create().setTlsStrategy(new H2TlsStrategy(sslContext, NoopHostnameVerifier.INSTANCE)).build();
          final IOReactorConfig ioReactorConfig = IOReactorConfig.custom().setSoTimeout(Timeout.ofSeconds(5)).build();
          final MinimalHttpAsyncClient client = HttpAsyncClients.createMinimal(HttpVersionPolicy.FORCE_HTTP_2, H2Config.DEFAULT, null, ioReactorConfig, connectionManager);
      
          client.start();
          final HttpHost target = new HttpHost("localhost", 8082, "https");
          final Future<AsyncClientEndpoint> leaseFuture = client.lease(target, null);
          final AsyncClientEndpoint endpoint = leaseFuture.get(10, TimeUnit.SECONDS);
          try {
              String[] requestUris = new String[] {"/"};
              CountDownLatch latch = new CountDownLatch(requestUris.length);
              for (final String requestUri: requestUris) {
                  SimpleHttpRequest request = SimpleHttpRequest.get(target, requestUri);
                  endpoint.execute(SimpleRequestProducer.create(request), SimpleResponseConsumer.create(), new FutureCallback<SimpleHttpResponse>() {
                          @Override
                          public void completed(final SimpleHttpResponse response) {
                              latch.countDown();
                              System.out.println(requestUri + "->" + response.getCode());
                              System.out.println(response.getBody());
                          }
      
                          @Override
                          public void failed(final Exception ex) {
                              latch.countDown();
                              System.out.println(requestUri + "->" + ex);
                              ex.printStackTrace();
                          }
      
                          @Override
                          public void cancelled() {
                              latch.countDown();
                              System.out.println(requestUri + " cancelled");
                          }
      
                      });
              }
              latch.await();
          } catch (Exception e) {
              e.printStackTrace();
          }finally {
              endpoint.releaseAndReuse();
          }
      
          client.shutdown(ShutdownType.GRACEFUL);
      }
      

      参考:https://hc.apache.org/httpcomponents-client-5.0.x/examples-async.html

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-22
        • 1970-01-01
        • 2011-03-14
        • 2021-03-15
        • 1970-01-01
        • 2019-05-04
        相关资源
        最近更新 更多