首页 > 解决方案 > 有没有办法将 Flux 作为表单数据提供给 WebClient 的主体?

问题描述

我想使用 WebClient 访问一些受限资源,因此需要提供登录名和密码并将其编码为表单数据。它就像那样工作得很好

private Mono<MyDataType> getMyDataType() {
    return WebClient.builder().build().post()
            .uri(MY_URI)
            .contentType(MediaType.APPLICATION_FORM_URLENCODED)
            .body(BodyInserters.fromFormData(getFormData()))
            .exchange()
            .flatMap(clientResponse -> clientResponse.bodyToMono(MyDataType.class));
}

private MultiValueMap<String, String> getFormData() {
    MultiValueMap<String, String> credentials = new LinkedMultiValueMap<>();
    credentials.add("login", readLoginStringFromDiskAsString);
    credentials.add("password", readPasswordStringFromDiskAsString);
}

但是,read*正如您所见,我的功能是阻塞式的 - 简单Files.readAllBytes,就像您在任何其他应用程序中所做的那样。我想将此读取从磁盘转换为更异步的东西,例如使用 DataBufferUtils 或类似的东西。fromFormData问题是,Spring 仅提供-的一种实现fromFormData(MultiValueMap<String, String> formData)

有没有办法真正实现这一目标?

标签: javaspring-webfluxproject-reactor

解决方案


您可以更改您的getFormData方法以返回Mono<MultiValueMap<String, String>>并平面映射其结果以异步访问凭据

private Mono<MultiValueMap<String, String>> getFormDataNonBlocking() {
    //asynchronous nonblocking reading of the credentials
}

private Mono<MyDataType> getMyDataType() {
    return getFormDataNonBlocking()
            .flatMap(credentials -> WebClient.builder()
                    .build()
                    .post()
                    .uri(MY_URI)
                    .contentType(MediaType.APPLICATION_FORM_URLENCODED)
                    .body(BodyInserters.fromFormData(credentials))
                    .exchange()
                    .flatMap(clientResponse -> clientResponse.bodyToMono(MyDataType.class)));
}

有一个注释。您不应该WebClient为每个请求创建新的。使用WebClient.Builder来自 Spring Boot 的预定义 bean 或重用您自己的一个实例。


推荐阅读