有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java在现代Spring中应该如何同步http请求?

很长一段时间以来,Spring一直建议同步http请求使用RestTemplate。然而,现在的文件说:

NOTE: As of 5.0 this class is in maintenance mode, with only minor requests for changes and bugs to be accepted going forward. Please, consider using the org.springframework.web.reactive.client.WebClient which has a more modern API and supports sync, async, and streaming scenarios.

但是我还没有看到如何建议在同步场景中使用WebClient。在documentation中有这样的内容:

WebClient can be used in synchronous style by blocking at the end for the result

我见过一些代码库使用。到处都是。然而,我的问题是,凭借在反应式框架方面的一些经验,我逐渐认识到阻止反应式调用是一种代码气味,应该只在测试中使用。例如this page

Sometimes you can only migrate part of your code to be reactive, and you need to reuse reactive sequences in more imperative code.

Thus if you need to block until the value from a Mono is available, use Mono#block() method. It will throw an Exception if the onError event is triggered.

Note that you should avoid this by favoring having reactive code end-to-end, as much as possible. You MUST avoid this at all cost in the middle of other reactive code, as this has the potential to lock your whole reactive pipeline.

那么,我是否错过了一些可以避免block()的功能,但允许您执行同步调用,或者在任何地方都使用block()真的是这样吗

或者WebClient API的意图是暗示人们不应该再在代码库中的任何地方进行阻塞?由于WebClient似乎是Spring提供的未来http调用的唯一替代方案,因此在整个代码库中使用非阻塞调用,并更改代码库的其余部分以适应这种情况,是未来唯一可行的选择吗

有一个相关的问题here,但它只关注正在发生的异常,而我想听听一般的方法应该是什么


共 (1) 个答案

  1. # 1 楼答案

    首先根据WebClient Java docs

    public interface WebClient Non-blocking, reactive client to perform HTTP requests, exposing a fluent, reactive API over underlying HTTP client libraries such as Reactor Netty. Use static factory methods create() or create(String), or builder() to prepare an instance.

    因此,webClient的创建并不是为了以某种方式进行阻止

    然而,webClient返回的响应可以是<T> reactor.core.publisher.Flux<T>类型,其他时间可以是<T> reactor.core.publisher.Mono<T>类型。来自反应堆项目的通量和Mono是有阻塞方法的ResponseSpec from WebClient.

    WebClient被设计成一个反应式客户端

    正如您可能从其他语言的其他反应式库(例如RxJs for javascript)中看到的,反应式编程通常基于函数式编程

    来自reactor项目的FluxMono在这里发生的事情是,它们允许您进行block(),以便在不需要函数编程的情况下进行同步执行

    这是一个article的一部分,我觉得很有趣

    Extractors: The Subscribers from the Dark Side

    There is another way to subscribe to a sequence, which is to call Mono.block() or Mono.toFuture() or Flux.toStream() (these are the "extractor" methods — they get you out of the Reactive types into a less flexible, blocking abstraction). Flux also has converters collectList() and collectMap() that convert from Flux to Mono. They don’t actually subscribe to the sequence, but they do throw away any control you might have had over the suscription at the level of the individual items.

    Warning A good rule of thumb is "never call an extractor". There are some exceptions (otherwise the methods would not exist). One notable exception is in tests because it’s useful to be able to block to allow results to accumulate. These methods are there as an escape hatch to bridge from Reactive to blocking; if you need to adapt to a legacy API, for instance Spring MVC. When you call Mono.block() you throw away all the benefits of the Reactive Streams

    那么,你能在不使用block()操作的情况下进行同步编程吗

    是的你可以但是你必须从函数式编程的角度来思考 谢谢你的申请

    范例

       public void doSomething1( ) {
          webClientCall_1....subscribe( response1 -> {
    
              ...do something else ...
              webClientCall_2....subscribe( response2 -> {
                  ...do something else more with response1 and response2 available here...
                });
           });
       }
    

    这被称为订阅回调地狱。您可以使用.block()方法来避免它,但正如所提供的文章所提到的那样,它们抛弃了该库的反应性