Отправка запроса с заголовками в третьи части API с помощью WebClient - PullRequest
0 голосов
/ 20 февраля 2019

Мне действительно нравится решение, которое у меня есть с RestTemplate, но скоро оно будет отменено в будущих весенних выпусках.Я пытаюсь отправить какой-то текст стороннему API, используя WebClient

  String text = URLEncoder.encode(text,"UTF-8");

        WebClient webClient = WebClient.builder()
            .baseUrl(BASE_URL)
            .defaultHeader("Key","af999-e99-4456-b556-4ef9947383d")
            .defaultHeader("src", srcLang)
            .defaultHeader("tgt", tgtLang)
            .defaultHeader("text", text)
            .build();

Затем отправьте сообщение здесь:

Mono<String> response = webClient.post().uri("/google/rtv/text")
            .retrieve()
            .bodyToMono(String.class);

Пытаясь проанализировать на основе устаревшего ответа:

private String parseJson( Mono<String> response) {
        ObjectMapper mapper = new ObjectMapper();
        JsonNode root = null;
        JsonNode review = null;


        //TODO: create an object and map it here. We need to save the original review too.
        try {
            root = mapper.readTree(response.toString());
            review = root.path("message");

        } catch (IOException e) {
            e.printStackTrace();
        }

        return review.asText();
    }

Позже мне нужно разобрать ответ, но сейчас я получаю сообщение об ошибке:

com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'MonoFlatMap': was expecting ('true', 'false' or 'null')
 at [Source: (String)"MonoFlatMap"; line: 1, column: 23]

и позже:

java.lang.NullPointerException: null

То, что я пытаюсь сделать, это то, что я сделал с RestTemplate.

Примерно так:

UriComponentsBuilder builder = UriComponentsBuilder
            .fromUriString(URL)
            .queryParam("src", src)
            .queryParam("tgt", tgt)
            .queryParam("text", text);

ResponseEntity<String> response = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, request, String.class);

, затем установите мой заголовок дляглобальная подписка.

  private ClientHttpResponse intercept(HttpRequest request, byte[] body,
                                         ClientHttpRequestExecution execution) throws IOException {
        request.getHeaders().add("Key","af999-e99-4456-b556-4ef9947383d");
        ClientHttpResponse response = execution.execute(request, body);
        return response;
    }

    @Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = new RestTemplate();
        restTemplate.setInterceptors(Collections.singletonList(this::intercept));
        return restTemplate;
    }

Советы?

1 Ответ

0 голосов
/ 20 февраля 2019

Проблема возникает здесь:

root = mapper.readTree(response.toString());

Этот фрагмент кода пытается сериализовать Mono<String> в виде строки, когда Mono является реактивным типом, который может обеспечитьэто String значение в конечном итоге.

Вы можете вызвать response.block() и получить результирующий String, но это будет блокирующий вызов, и Reactor запрещает это, если находится в середине реактивного выполнения.Это сделано по уважительным причинам, так как это заблокирует один из немногих потоков, которые использует ваше веб-приложение, и может заставить его перестать обслуживать другие запросы.

Вместо этого у вас может быть что-то вроде:

Mono<String> review = response.map(r -> parseJson(r);

И затем повторно используйте это новое значение в строке.

Обратите внимание, что WebClient изначально поддерживает десериализацию JSON, и вы можете десериализовать всю полезную нагрузку следующим образом:

Mono<Review> review = webClient.post().uri("/google/rtv/text")
        .retrieve()
        .bodyToMono(Review.class);
...