使用Spring WebClient重复过滤响应。

huangapple go评论74阅读模式
英文:

Repeatedly filter a response using Spring WebClient

问题

我是新手使用Spring,对WebClient更是一窍不通。我想要使用Spring的WebClient,以1秒的间隔重复过滤Get响应的主体,持续2分钟。我正在执行一个返回空JSON字符串列表的Get请求。在某个时刻,这个主体将被填充,我想要返回这个字符串列表。我想要以这样的方式过滤响应,当它为空时,继续执行请求,直到被填充并返回所需结果。

private List<String> checkUser() {
    List<String> ibanList = new ArrayList<>();

    ExchangeFilterFunction filter = ExchangeFilterFunction.ofResponseProcessor(clientResponse -> {
        if (clientResponse.body())
              // 在此处进行处理
    });

    Optional<Account[]> accountsOptional = webClient.get()
            .uri("example.com")
            .accept(MediaType.APPLICATION_JSON)
            .retrieve()
            .bodyToMono(Account[].class)
            .delaySubscription(Duration.ofSeconds(1))
            .retry()
            .filter(filter)
            .blockOptional(Duration.ofMinutes(2));

    if (accountsOptional.isPresent()) {
        for (Account account : accountsOptional.get()) {
            ibanList.add(account.getIban());
        }
        return ibanList;
    }
    return null;
}

有人知道如何实现这个吗?任何帮助将不胜感激。

英文:

I'm new to Spring and even newer to WebClient. I want to filter the body of a Get response repeatedly with one second intervals for 2 minute duration using Springs' WebClient. I'm performing a get request which returns an empty JSON list of strings. At some moment of time the body is going to be populated and I want to return this list of strings. I want to filter the response in such way, that when it is empty it continues to perform the request until it is populated and return the desired result.

 private List&lt;String&gt; checkUser() {
        List&lt;String&gt; ibanList = new ArrayList&lt;&gt;();

        ExchangeFilterFunction filter = ExchangeFilterFunction.ofResponseProcessor(clientResponse -&gt; {
            if (clientResponse.body())
                  //something here

        });

        Optional&lt;Account[]&gt; accountsOptional = webClient.get()
                .uri(&quot;example.com&quot;)
                .accept(MediaType.APPLICATION_JSON)
                .retrieve()
                .bodyToMono(Account[].class)
                .delaySubscription(Duration.ofSeconds(1))
                .retry()
                .filter(filter)
                .blockOptional(Duration.ofMinutes(2));

        if (accountsOptional.isPresent()) {

            for (Account account : accountsOptional.get()) {
                ibanList.add(account.getIban());
            }
            return ibanList;
        }
        return null;
    }

Does anybody have an idea how to do this? Any help would be appreciated.

答案1

得分: 1

对我起作用的方法是使用flatMap在列表为空时抛出异常,然后调用retryWhen,直到列表填充。 (blockOptional已删除,因为不再需要)

Account[] accounts = webClient.get()
                    .uri("example.com")
                    .accept(MediaType.APPLICATION_JSON)
                    .retrieve()
                    .bodyToMono(Account[].class)
                    .delaySubscription(Duration.ofSeconds(1))
                    .flatMap(resp -> {
                        if (resp.length == 0) {
                            return Mono.error(Exception::new);
                        } else {
                            return Mono.just(resp);
                        }
                    })
                    .retryWhen(Retry.max(60))
                    .block();
英文:

What did the trick for me was using flatMap to throw exception when the list is empty and then calling retryWhen, until the list is populated. (blockOptional removed, because not needed anymore)

Account[] accounts = webClient.get()
                    .uri(&quot;example.com&quot;)
                    .accept(MediaType.APPLICATION_JSON)
                    .retrieve()
                    .bodyToMono(Account[].class)
                    .delaySubscription(Duration.ofSeconds(1))
                    .flatMap(resp -&gt; {
                        if (resp.length == 0) {
                            return Mono.error(Exception::new);
                        } else {
                            return Mono.just(resp);
                        }
                    })
                    .retryWhen(Retry.max(60))
                    .block();

答案2

得分: 0

你可以使用bodyToFlux而不是bodyToMono,然后使用interval方法。你可以像这样分离出请求:

Flux<Account[]> request = webClient.get()
                .uri("example.com")
                .accept(MediaType.APPLICATION_JSON)
                .retrieve()
                .bodyToFlux(Account[].class);

然后使用interval进行调用:

Flux.interval(Duration.ofSeconds(1), Duration.ofMinutes(2))
  .map(i -> request)...

然后你可以将筛选逻辑链接到这里。

英文:

Instead of using bodyToMono you could use bodyToFlux instead and then use the interval method. You could separate out the request like this:

Flux&lt;Account[]&gt; request = webClient.get()
                .uri(&quot;example.com&quot;)
                .accept(MediaType.APPLICATION_JSON)
                .retrieve()
                .bodyToFlux(Account[].class);

and then call at interval using

Flux.interval(Duration.ofSeconds(1), Duration.ofMinutes(2))
  .map(i -&gt; request)...

you can then chain your filter logic to this

huangapple
  • 本文由 发表于 2020年8月4日 18:56:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/63245391.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定