5

Próbuję nowego WebClient z Spring 5 (5.0.0.RC2) w bazie kodu, która używa programowania reaktywnego i miałem już sukces mapowania odpowiedzi JSON z punktu końcowego na DTO w mojej aplikacji, która działa bardzo nicea:Jak najlepiej uzyskać tablicę bajtów od ClientResponse ze Spring WebClient?

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

jednak teraz próbuję organizmie odpowiedź z punktu końcowego, który używa protokołu bufory (dane binarne służył jako application/octet-stream), więc chciałbym dostać surowe bajty z odpowiedzi, które Sam będę mapował do obiektu.

Dostałem go do pracy tak użyciu Bytes z Google Guava:

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) 

To działa, ale jest łatwiejszy, bardziej elegancki sposób, aby uzyskać te bajty?

Odpowiedz

8

ClientResponse.bodyToMono() na końcu używa jakiegoś org.springframework.core.codec.Decoder, który twierdzi, że obsługuje określoną klasę.

Powinniśmy zatem sprawdzić hierarchię klas Decoder, w szczególności gdzie i jak jest wdrażana metoda decodeToMono().

Jest StringDecoder który wspiera dekodowanie do String, grono Jackson związanych dekoderów (stosowany w przykładzie DTO pod maską), a tam jest również ResourceDecoder który jest przedmiotem szczególnego zainteresowania.

obsługuje org.springframework.core.io.InputStreamResource i org.springframework.core.io.ByteArrayResource. ByteArrayResource jest w zasadzie opakowaniem około byte[], więc poniższy kod zapewni dostęp do treści odpowiedzi jako tablica bajtów:

Mono<byte[]> mono = client.get() 
      ... 
      .exchange() 
      .flatMap(response -> response.bodyToMono(ByteArrayResource.class)) 
      .map(ByteArrayResource::getByteArray);