1

java.net.httpJava 11 では、 HTTP 要求を行うための新しいパッケージ が導入されています。一般的な使用法では、かなり簡単です。

私の質問はjava.net.http、各チャンクがクライアントによって受信されるときに、チャンクされた応答をどのように処理するのですか?

java.http.netBodySubscriber私が欲しいもののように見えるリアクティブが含まれていますが、それがどのように使用されているかの例が見つかりません。

http_get_demo.py

以下は、到着時にチャンクを出力する Python 実装です。java.net.http で同じことをしたいと思います。

import argparse
import requests


def main(url: str):
    with requests.get(url, stream=True) as r:
        for c in r.iter_content(chunk_size=1):
            print(c.decode("UTF-8"), end="")


if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description="Read from a URL and print as text as chunks arrive")
    parser.add_argument('url', type=str, help="A URL to read from")
    args = parser.parse_args()

    main(args.url)

HttpGetDemo.java

完全を期すために、java.net.http を使用してブロック リクエストを作成する簡単な例を次に示します。

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpResponse;
import java.net.http.HttpRequest;

public class HttpGetDemo {

  public static void main(String[] args) throws Exception {

    var request = HttpRequest.newBuilder()
            .uri(URI.create(args[0]))
            .build();

    var bodyHandler = HttpResponse.BodyHandlers
            .ofString();

    var client = HttpClient.newHttpClient();
    var response = client.send(request, bodyHandler);
    System.out.println(response.body());

  }
}

HttpAsyncGetDemo.java

そして、非ブロッキング/非同期リクエストを作成する例を次に示します。

import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpResponse;
import java.net.http.HttpRequest;

/**
 * ReadChunked
 */
public class HttpAsyncGetDemo {

  public static void main(String[] args) throws Exception {

    var request = HttpRequest.newBuilder()
            .uri(URI.create(args[0]))
            .build();

    var bodyHandler = HttpResponse.BodyHandlers
            .ofString();

    var client = HttpClient.newHttpClient();

    client.sendAsync(request, bodyHandler)
            .thenApply(HttpResponse::body)
            .thenAccept(System.out::println)
            .join();

  }
}
4

4 に答える 4

2

s はそのまま出力できますが、 a がチャンクに対応するというByteBuffer保証はありません。ByteBufferチャンクはスタックによって処理されます。ByteBufferチャンクごとに1 つのスライスがプッシュされますが、バッファに十分なスペースが残っていない場合は、部分的なチャンクがプッシュされます。コンシューマーが見るのはByteBuffer、データを含む のストリームだけです。したがって、できることは、それらByteBufferの s をそのまま出力することですが、サーバーから送信されたそれぞれが正確に 1 つのチャンクに対応するという保証はありません。

注: リクエストの本文がテキスト ベースの場合は、 各行をそのまま出力するBodyHandlers.fromLineSubscriber(Subscriber<? super String> subscriber)カスタムを使用できます。Subscriber<String>BodyHandlers.fromLineSubscriber、応答ヘッダーに示されている文字セットを使用してバイトを文字にデコードするというハードワードを実行し、必要に応じてバイトをデコードできるようになるまでバッファリングします (テキストに複数のバイトでエンコードされた文字が含まれている場合、ByteBuffer はエンコードシーケンスの途中で終了する可能性があります)。 、行の境界でそれらを分割します。Subscriber::onNext メソッドは、テキストの各行に対して 1 回呼び出されます。https://download.java.net/java/early_access/jdk11/docs/api/java.net.http/java/net/http/HttpResponse.BodyHandlers.html#fromLineSubscriber(java.util.concurrent.Flow.Subscriber)を参照してください)詳細については。

于 2018-10-12T17:03:34.303 に答える