web-dev-qa-db-ja.com

Spring WebClientのClientResponseからバイト配列を取得する最良の方法は?

私は、Spring 5(5.0.0.RC2)の新しいWebClientをリアクティブプログラミングを使用するコードベースで試してみましたが、エンドポイントからのJSON応答をアプリのDTOにマッピングすることに成功しました。それはとてもうまくいきます:

WebClient client = WebClient.create(baseURI);
Mono<DTO> dto = client.get()
        .uri(uri)
        .accept(MediaType.APPLICATION_JSON)
        .exchange()
        .flatMap(response -> response.bodyToMono(DTO.class));

ただし、今はプロトコルバッファー(バイナリデータがapplication/octet-stream)なので、レスポンスから生のバイトを取得し、それを自分でオブジェクトにマッピングします。

Google GuavaのBytesを使用して、次のように機能するようにしました。

Mono<byte[]> bytes = client.get()
        .uri(uri)
        .accept(MediaType.APPLICATION_OCTET_STREAM)
        .exchange()
        .flatMapMany(response -> response.body(BodyExtractors.toDataBuffers()))
        .map(dataBuffer -> {
            ByteBuffer byteBuffer = dataBuffer.asByteBuffer();
            byte[] byteArray = new byte[byteBuffer.remaining()];
            byteBuffer.get(byteArray, 0, bytes.length);
            return byteArray;
        })
        .reduce(Bytes::concat)

これは機能しますが、これらのバイトを取得するより簡単でエレガントな方法はありますか?

14
Nils Breunese

最後にClientResponse.bodyToMono()は、指定されたクラスをサポートすると主張する_org.springframework.core.codec.Decoder_をいくつか使用します。

したがって、Decoderのクラス階層、特にdecodeToMono()メソッドが実装されている場所と方法を確認する必要があります。

StringDecoderへのデコードをサポートするStringがあります。これは、Jackson関連のデコーダーの束(DTOの例で内部的に使用されています)であり、ResourceDecoderもあります。特に興味深い。

ResourceDecoderは_org.springframework.core.io.InputStreamResource_および_org.springframework.core.io.ByteArrayResource_をサポートします。 ByteArrayResourceは基本的に_byte[]_のラッパーであるため、次のコードはバイト配列として応答本文へのアクセスを提供します。

_Mono<byte[]> mono = client.get()
            ...
            .exchange()
            .flatMap(response -> response.bodyToMono(ByteArrayResource.class))
            .map(ByteArrayResource::getByteArray);
_
28
Oleg Estekhin