Есть ли способ предоставить Flux телу WebClient в виде данных формы? - PullRequest
0 голосов
/ 03 апреля 2019

Я хочу использовать 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 голосов
/ 03 апреля 2019

Вы можете изменить метод 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 bean-компонент из Spring Boot или используйте один свой собственный экземпляр.

...