Миграция с RestTemplate на WebFlux

У меня есть RestTemplate, который я хочу перенести на клиент WebFlux:

RestTemplate restTemplate = new RestTemplate();
String url = "https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml";
ResponseEntity<Envelope> response = restTemplate.getForEntity(url, Envelope.class);

Я попробовал это:

Boolean webClient = WebClient.builder()
                .build()
                .get()
                .uri("https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml")
                .accept(MediaType.APPLICATION_XML)
                .exchangeToMono(res -> Mono.just(res.statusCode().equals(HttpStatus.OK)))
                .timeout(Duration.ofSeconds(2))
                .block();

Мне не ясно, как я могу получить ответ и прочитать его как JAVA DTO. Знаете, как мне реализовать его код?

0
0
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Чтобы сделать запрос и получить ответ, вам нужно вызвать функцию retrieve в WebClient. Затем вы можете проанализировать тело ответа с помощью bodyToMono. Важно знать, что Mono — это один объект, а Flux — это типы коллекций.

Envelope envelope = WebClient.builder()
                .build()
                .get()
                .uri("https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml")
                .accept(MediaType.APPLICATION_XML)
                .exchangeToMono(res -> Mono.just(res.statusCode().equals(HttpStatus.OK)))
                .timeout(Duration.ofSeconds(2))
                .retrieve()
                .bodyToMono(Envelope.class)
                .block();

На этой странице также есть хороший пример и объяснение: https://www.baeldung.com/webflux-webclient-parameters

Но я бы посоветовал вам немного больше структурировать свой код. Например, когда вы используете Spring Boot, подумайте об использовании этого WebClientBuilder для создания WebClient как Bean, этот WebClient будет настроен на наличие базового URL-адреса (https://www.ecb.europa.eu). Затем у вас есть сервис, в который вы внедряете этот веб-клиент и совершаете вызов, чтобы получить свой конверт. Что-то вроде этого позволит вам использовать один и тот же WebCLient для разных вызовов одного и того же хоста:

import java.util.List;
import java.util.concurrent.TimeUnit;

import io.netty.channel.ChannelOption;
import io.netty.handler.timeout.ReadTimeoutHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.client.reactive.ClientHttpConnector;
import org.springframework.http.client.reactive.ReactorClientHttpConnector;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.netty.http.client.HttpClient;

@Configuration
public class RestConfig {
    @Bean
    public WebClient ecbEuropaWebClient(WebClient.Builder webClientBuilder) {
        HttpClient httpClient = HttpClient.create().tcpConfiguration(
                (client) -> client.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 2000).doOnConnected(
                        (connection) -> connection.addHandlerLast(
                                new ReadTimeoutHandler(2000, TimeUnit.MILLISECONDS))));
        ClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);
        return webClientBuilder
                .baseUrl("https://www.ecb.europa.eu")
                .clientConnector(connector)
                .build();
    }
}

@Service
public class EcbEuropaService {
    @Autowired
    private WebClient ecbEuropaWebClient;

    public Envelope getEnvelope() {
        return ecbEuropaWebClient.get()
                .uri(uriBuilder -> uriBuilder.path("/stats/eurofxref/eurofxref-daily.xml").build())
                .accept(MediaType.APPLICATION_XML).retrieve().bodyToMono(Envelope.class).block();
    }
}

У меня есть несколько объектов в конверте. И могу ли я удалить код block()?

Peter Penzov 17.05.2024 17:56

Если у вас есть коллекция типа List<Envelope>, вам нужно использовать bodyToFlux. Вы можете удалить блок, если используете Springs Reactive Stack. Если вы используете классический стек сервлетов, вам понадобится блок.

kSp 17.05.2024 18:06

Еще один дополнительный вопрос. В классическом приложении весенней загрузки какой клиент для отдыха дает больше преимуществ RestTemplate или WebFlux?

Peter Penzov 17.05.2024 23:09

Это зависит от того, чего вы пытаетесь достичь. Например, мне было очень сложно добавить потоки OpenID в RestTemplate, но с WebClient это было довольно легко. Также я думаю, что WebClient будет более перспективным. Здесь также есть хорошее сравнение: medium.com/@kmrpushkar09/…

kSp 18.05.2024 08:56

Также вы можете написать уровень абстракции, который позволит вам очень гибко изменять используемые технологии. Но в зависимости от вашего варианта использования это может быть излишним. Также есть Apache HttpClient, на который стоит обратить внимание.

kSp 18.05.2024 08:57

Другие вопросы по теме