有没有办法将Flux作为Form Data提供给WebClient的主体?

时间:2019-04-03 14:48:03

标签: java spring-webflux project-reactor

我想使用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或类似内容。问题是,Spring仅提供fromFormData-fromFormData(MultiValueMap<String, String> formData)的一种实现。

真的有办法实现吗?

1 个答案:

答案 0 :(得分:0)

您可以更改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。使用Spring Boot中预定义的WebClient.Builder bean或重用您自己的一个实例。