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

Spring reactive webClient-如何在Mono上调用方法

漆雕疏珂
2023-03-14

对于反应编程和尝试通过WebFlux和WebClient创建反应服务是新的。

方法的流程类似于

  1. 发布请求并等待返回响应
  2. 映射服务的响应体(具有其他业务逻辑),并返回建议类型
  3. 创建ResponseEntity
  4. 创建Mono
  5. 类型的Mono
private Mono<ResponseEntity<Recommendations>> myMethod(final Request request, final String variantName) {

    Mono<String> response = webClient.build()
            .post()
            .uri(uri)
            .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
            .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
            .bodyValue(requestBody)
            .retrieve().bodyToMono(String.class);

    var recommendations = ((XYZResponseMapper) responseMapper).mapReactive(request, response, useCaseId, variantName); //return type Recommendations
    var entity = new ResponseEntity<>(recommendations, nullHeaders, HttpStatus.OK);
    return Mono.just(entity);

}

共有1个答案

蒋联
2023-03-14

简短的答案很可能是否定的。

更长的版本是,当某人开始订阅您的服务(它是一个生产者)时,客户端希望使用数据。订阅一开始,webflux就要在应用程序内部构建反应链。这个链可以与一种回调链相比较,被称为“组装阶段”。

在这个组装阶段,重要的是每个通量/单声道的返回是相互连接的。否则你就会破坏链条。

var firstAction = Mono.just("Hello").flatMap(value -> {
    // do something
});

// Next action needs to chain on the last
var secondAction = firstAction.flatMap(value -> {
    // Do the next thing
});

// Can be combined
var bothActions = Mono.just("Hello").flatMap(value -> {
    // do something
}).flatMap(value -> {
    // do next thing
});

private Mono<ResponseEntity<Recommendations>> myMethod(final Request request, final String variantName) {

    // Here you have a response
    Mono<String> response = webClient.build()
            .post()
            .uri(uri)
            // Not needed content type will default to json
            .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
            // will also default to json
            .header(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
            .bodyValue(requestBody)
            .retrieve().bodyToMono(String.class);

    // here you pass the response into a function, hence probably breaking the chain
    var recommendations = ((XYZResponseMapper) responseMapper).mapReactive(request, response, useCaseId, variantName); //return type Recommendations
    var entity = new ResponseEntity<>(recommendations, nullHeaders, HttpStatus.OK);

    // Here you are suddenly creating a new mono, which tells me you deffo broke the chain and need to recreate it by doing a mono#just
    return Mono.just(entity);

}

那么我们该怎么解决呢?

private Mono<Recommendations> myMethod(final Request request, final String variantName) {
    // You should not build a webclient on each request, you should build it in a @Bean
    final Mono<XYZResponse> response = webClient.build()
            .post()
            .uri(uri)
            .bodyValue(requestBody)
            .retrieve()
            // Map into a class representation to uphold type safety
            .bodyToMono(XYZResponse.class);

    // if we need to do additional transformations we can flatMap and chain on
    final Mono<Recommendations> recommendations = response.flatMap(value -> {
        var recommendations = mapper.toRecommendations(value);
    });

    // No need to wrap it in a response webflux will do that for you automatically when you return it to the client
    return recommendations;
}

然后我们甚至可以把它改写得更短。

private Mono<Recommendations> myMethod(final Request request, final String variantName) {
    return webClient.build()
            .post()
            .uri(uri)
            .bodyValue(requestBody)
            .retrieve()
            .bodyToMono(XYZResponse.class)
            .flatMap(value -> {
                var recommendations = mapper.toRecommendations(value);
            });
}

我通常把return语句写在第一行,然后再写我的chain。

@Configuration
public class ClientConfig {

    @Bean
    public WebClient webclient(WebClient.Builder webClient) {
        return webClient.baseUrl( ... )
                .build();
    }
}

@Component
public class RecommendationHandler {

    final private WebClient 

    @Autowire
    public RecommendationHandler(WebClient webClient) {
        this.webClient = webClient;
    }

    private Mono<Recommendations> getRecommendations(RequestBody requestBody) {
    return webClient
            .post()
            .bodyValue(requestBody)
            .retrieve()
            .bodyToMono(XYZResponse.class)
            .flatMap(value -> {
                var recommendations = mapper.toRecommendations(value);
            });
    }   
}
 类似资料:
  • 我在UserResource中有一个具有这种签名的方法。我正在测试的java(rest控制器): 这里的关键时刻是@AuthenticationMain(我们有一个自定义类)作为方法参数传递。 我在测试中所做的是将UserResources自动连接到测试类中,并尝试调用getUsers方法 故障原因如下: 我知道它可能不像只是传递一个构造的User对象那样简单,因为Spring无法正确解析它,但是

  • 我尝试使处理程序和路由器类的Spring引导webflow。模型类是用户类。代码是 下面是webflux项目的处理程序类。在register方法中,我编写了id复制测试代码。但这是完全错误的。 我想提取的用户名或id字符串从Mono的Spring webflow.将需要任何评论。我被这部分卡住了。

  • 问题内容: 注意:这旨在作为常见问题的规范答案。 我有一个带有字段()的Spring 类(),但是该字段是我尝试使用它时所用的。日志显示同时创建了bean和bean,但是每当尝试在服务bean上调用方法时,我都会得到一个。Spring为什么不自动接线该领域? 控制器类: 服务等级: 应该自动连接的服务bean,但不是: 当我尝试时,出现以下异常: 问题答案: 带注释的字段是因为Spring不知道您

  • 我对反应性非常陌生,所以在范式转变中有点挣扎,但是也许有人能帮我克服这个问题? 我的控制器将Mono(称为“limit”)作为服务参数传递给我的服务。Mono在subscribe上发出一个整数,服务使用该整数执行其工作,该整数返回一个流量。 在我的服务方法中,我需要订阅mono,但我需要在我的服务方法(对其他endpoint进行web客户端REST调用)之前订阅mono,因为REST调用中需要限制

  • 我的代码是这样构造的- 我正在努力实现这一点: 方法1()返回地址时,我需要使用它并调用方法2()来更新MongoDB文档中的地址。也没有抛出异常。但是我没有看到任何日志在方法2() 代码: 虽然调用了method2(),但MongoDB中的文档更新没有发生。

  • 问题内容: 假设我有汽车清单: 如何缩短上面的代码?简而言之,如何在List的每个元素上调用方法? 例如,在Python中: 问题答案: 更新: 有关使用lambda表达式的Java8解决方案,请参见aaiezza的答案。 Java 8之前的原始答案: 使用Guava可以实现效果,实现比您现有的更加冗长: (请记住,返回的视图将延迟应用该函数- 如果要立即复制,则需要将返回的列表复制到新列表中。)