从RestTemplate迁移至WebFlux:如何将响应映射为Java DTO?
从RestTemplate迁移到WebClient:XML响应转Java DTO
原RestTemplate实现
RestTemplate restTemplate = new RestTemplate(); String url = "https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml"; ResponseEntity<Envelope> response = restTemplate.getForEntity(url, Envelope.class);
你的WebClient尝试代码
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();
正确的WebClient实现(转换为Envelope DTO)
// 建议全局单例复用WebClient,避免重复创建 WebClient webClient = WebClient.builder() .baseUrl("https://www.ecb.europa.eu") .build(); // 同步获取DTO(适配原有同步逻辑) Envelope envelope = webClient.get() .uri("/stats/eurofxref/eurofxref-daily.xml") .accept(MediaType.APPLICATION_XML) .retrieve() // 自定义错误状态处理 .onStatus(HttpStatus::isError, response -> Mono.error(new RuntimeException("请求失败,状态码:" + response.statusCode())) ) // 将XML响应体直接转换为目标DTO .bodyToMono(Envelope.class) .timeout(Duration.ofSeconds(2)) .block(); // 异步场景推荐写法(无需block,返回Mono让调用方订阅) // Mono<Envelope> envelopeMono = webClient.get() // .uri("/stats/eurofxref/eurofxref-daily.xml") // .accept(MediaType.APPLICATION_XML) // .retrieve() // .onStatus(HttpStatus::isError, response -> // Mono.error(new RuntimeException("请求失败,状态码:" + response.statusCode())) // ) // .bodyToMono(Envelope.class) // .timeout(Duration.ofSeconds(2));
核心要点说明
bodyToMono(Envelope.class):这是实现XML转DTO的关键,对应RestTemplate的类型转换逻辑。WebClient会通过内置的Jaxb2XmlDecoder解析XML,需确保你的Envelope类有正确的JAXB注解(比如@XmlRootElement、@XmlElement等)。retrieve()简化处理:相比exchangeToMono(),retrieve()是更简洁的响应处理方式,自动识别2xx状态码,非2xx状态可通过onStatus()自定义错误逻辑。- WebClient实例复用:不要每次请求都创建WebClient实例,建议在Spring环境下通过
@Bean配置全局单例,提升性能。 - 同步vs异步:
block()仅用于适配原有同步代码,WebFlux的最佳实践是保持异步流程,返回Mono<Envelope>让调用方通过订阅处理结果。
内容的提问来源于stack exchange,提问作者Peter Penzov
相关产品推荐
相关产品推荐

