当前位置: 首页 > 知识库问答 >
问题:

SpringBootWebFlux-flatMap是链接http调用的正确方法吗?

尤钱明
2023-03-14

关于SpringWebFlux的小问题,以及如何“链接”http调用。

通过一个具体的例子,这里是一个非常简单的SpringMVC示例,带有一个rest模板。

RestTemplate restTemplate = new RestTemplate();

        HttpEntity<StepOneRequest> stepOneRequestHttpEntity = new HttpEntity<>(new StepOneRequest("foo", "bar"));
        StepOneResponse stepOneResponse = restTemplate.postForObject("https://step-one-web-service:443/getStepTwoFromFooBar", stepOneRequestHttpEntity, StepOneResponse.class);

        HttpEntity<StepTwoRequest> stepTwoRequestHttpEntity = new HttpEntity<>(new StepTwoRequest(stepOneResponse.getTheDependencyFromStepOne()));
        StepTwoResponse stepTwoResponse = restTemplate.postForObject("https://step-two-web-service:443/getResponseFromStepTwo", stepTwoRequestHttpEntity, StepTwoResponse);

        return ResponseEntity.ok(new MyResponse(stepTwoResponse.getImportantValueFromStepTwo()));
    }

在这个片段中,我们看到了非常简单的内容。仅初始化一个rest模板。

超文本传输协议请求有效载荷对象的构造。

使用所构建的对象来查询第一外部web应用API以获得响应。

重要的是,需要第一个HTTP调用的响应来进行第二个HTTP调用。它们只能是顺序的,它需要第一次调用的结果,才能查询第二个API。

然后,http调用第二个API。

最后,根据第二个API向原始请求者发送响应。

现在,如果将其转换为Webflux:

WebClient webClientStepOne = WebClient.create("https://step-one-web-service:443/getStepTwoFromFooBar");
        WebClient webClientStepTwo = WebClient.create("https://step-two-web-service:443/getResponseFromStepTwo");

        Mono<StepOneResponse> stepOneResponseMono = webClientStepOne.post().body(BodyInserters.fromValue(new StepOneRequest("foo", "bar"))).retrieve().bodyToMono(StepOneResponse.class);

        Mono<StepTwoResponse> stepTwoResponseMono = stepOneResponseMono.flatMap(aStepOneResponse -> webClientStepTwo.post().body(BodyInserters.fromValue(aStepOneResponse.getTheDependencyFromStepOne())).retrieve().bodyToMono(StepTwoResponse.class));

        return stepTwoResponseMono.map(aStepTwoResponse -> ResponseEntity.ok(new MyResponse(aStepTwoResponse.getImportantValueFromStepTwo())));
    }

我有一个大问题。虽然这是正确的(它会产生相同的响应),但这是正确的做法吗?

特别是平面图的线条

Mono<StepTwoResponse> stepTwoResponseMono = stepOneResponseMono.flatMap(aStepOneResponse -> webClientStepTwo.post().body(BodyInserters.fromValue(aStepOneResponse.getTheDependencyFromStepOne())).retrieve().bodyToMono(StepTwoResponse.class));

这似乎很不寻常。这里还有更好的办法吗?

另外,还有一个附带问题,如果我需要链接N个api调用,我们真的需要N个WebClient吗?URL是不同的,不仅仅是路径,还有完整的URL。当rest模板只能使用一个实例时,似乎在这里,如果我需要调用N个外部服务,我需要N个WebClient。

请问这里使用WebClient的正确方法是什么?请问,链接http调用的正确方法是什么?

非常感谢。

共有1个答案

拓拔嘉运
2023-03-14

我有一个大问题。虽然这是正确的(它会产生相同的响应),但这是正确的做法吗?

基本上,是的,你做得对。唯一不正确的是您的Webclient使用情况和您的风格。

您当然不必为每个URI指定WebClient(您也不应该这样做,因为它们是可重用的)因此,如果您有不同的域和相同的webclient,只需创建一个标准实例:

WebClient wc = WebClient.create();

...然后使用:

webClientStepOne.post()
                .uri("https://blah")

...在链的顶部,为同一实例指定不同的URI。

就风格而言——您会注意到,当代码被拆分为单独的变量并写在长行上时,代码会很快变得笨拙。尽管最初看起来似乎有悖常理,但在反应式领域中普遍接受的最佳实践是在一条语句中完成所有工作,将每个新方法调用的格式设置在单独的行中(使您能够向下阅读,然后查看反应链的执行情况)因此,在您的情况下,它将成为:

return wc.post().uri("https://step-one-web-service:443/getStepTwoFromFooBar")
        .body(BodyInserters.fromValue(new StepOneRequest("foo", "bar")))
        .retrieve()
        .bodyToMono(StepOneResponse.class)
        .flatMap(aStepOneResponse ->
                wc.post().uri("https://step-two-web-service:443/getResponseFromStepTwo")
                        .body(BodyInserters.fromValue(aStepOneResponse.getTheDependencyFromStepOne()))
                        .retrieve()
                        .bodyToMono(StepTwoResponse.class)
        )
        .map(aStepTwoResponse ->
                ResponseEntity.ok(new MyResponse(aStepTwoResponse.getImportantValueFromStepTwo()))
        );

您可以稍微整理一下,例如,通过将内部flatmap调用委托给一个单独的方法,但这实际上取决于首选项。

 类似资料:
  • 问题内容: 当每个呼叫都取决于之前的呼叫是否已完成时,我试图找到创建异步呼叫的最佳方法。目前,我通过递归调用定义的流程函数来链接方法,如下所示。 这就是我目前正在做的。 然后我将其称为如下 虽然这对我来说非常好,但我不禁认为必须有一种更好(更简单)的方法。以后我的递归调用变得太深时,会发生什么? 注意 :我不是在浏览器中使用javascript,而是在Titanium框架中使用本机,这类似于Nod

  • 问题内容: 在我的插件中,我有一些jQuery- Ajax代码,用于处理表单数据,并在单击按钮后立即将其添加到数据库中。由于许多人的插件文件夹路径不同,所以我想知道是否有某种方式可以标准化指向数据处理PHP文件的URL。请参阅下面的示例: 问题答案: 在WordPress中,所有AJAX请求都必须发送到以下URL: 您不应该直接向插件或主题目录中的文件发出AJAX请求。 另外,请勿对上面的URL进

  • 问题内容: 我读这个和这个,结果发现,在课堂上我需要保存到类的引用,当东西在发生类,我们执行由类的接口中定义的方法工具。好吧,我明白了。我以不同的方式使用接口来调用回调: 我发现这种方式更具可读性,更容易理解,但是不确定这是否是不好的做法。因此,我可以随意走这条路吗? 问题答案: 所以我可以随意走这条路吗? 这种方式不是很正确。 您在说的是称为Observer或/ 模式。 简而言之:订户想要从发布

  • 我读了这篇文章和这篇文章,发现在类中,我需要保存对类的引用,当类中发生一些事情时,我们执行一个由类实现的接口定义的方法。不知何故我明白了。我以不同的方式使用接口来调用回调: 我发现这种方式更易读,更容易理解,但不确定这是否是一个不好的做法。所以我可以自由地走得更远吗?

  • 我使用Apache HTTP客户端在我的REST API调用到某些Web服务的连池。 奇怪的是,尽管我使用了HTTP连接池,但我的性能并没有任何提高。 我正在使用Apache HTTP客户端连接到我的web服务,其中的代码如下所示: 我使用Spring的来包装使用Spring的