【问题标题】:How to use webClient in Spring Integration?如何在 Spring 集成中使用 webClient?
【发布时间】:2021-07-19 14:58:07
【问题描述】:

我正在尝试在我的 Spring Integration 应用程序中使用 webClient。 使用block() 方法我得到了这个错误:

org.springframework.messaging.MessageHandlingException: error occurred during processing message in 'MethodInvokingMessageProcessor' [org.springframework.integration.handler.MethodInvokingMessageProcessor@28b67bb]; nested exception is java.lang.IllegalStateException: block()/blockFirst()/blockLast() are blocking, which is not supported in thread reactor-http-nio-4
    at org.springframework.integration.support.utils.IntegrationUtils.wrapInHandlingExceptionIfNecessary(IntegrationUtils.java:192) ~[spring-integration-core-5.4.5.jar:5.4.5]
    Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:

所以我删除了block 以防止出现问题,但我看起来没有那个调用就不会执行。不知道怎么弄的

激活器

@ServiceActivator(
    inputChannel = "lisContractValidationChannel",
    outputChannel = "aopContractValidationReplyAndContinueRouterChannel"

)
public Application sendEContract(Application application) {
    
    ContractRequest contractRequest = prepareRequest(application);
    
    lisOperations.verifyContract(contractRequest,
        application.getContractData().getRouteOne().getConversationID(),
        application.getRouteOneId());
    
    return application;
}

运营

private final WebClient webClient;

@Override
public void verifyContract(
    EContractRequest contractRequest,
    String vendorTransactionId,
    String loanId) {

    
    webClient.post()
        .uri(baseUrl + contract)
        .header("sourceRequestId", sourceRequestId)
        .header("VENDOR-ID", String.join(";", List.of(vendorId, vendorTransactionId, loanId)))
        .bodyValue(contractRequest).retrieve().toEntity(LisResponse.class);
} 

WebClient 配置

@Bean
public WebClient webClient(MetricsDTWebClientFilterFunction metricsDTWebClientFilterFunction) {
    
    HttpClient httpClient = HttpClient
        .create();
    
    final WebClient.Builder webClientBuilder = WebClient.builder()
        .clientConnector(new ReactorClientHttpConnector(httpClient))
        .codecs(ClientCodecConfigurer::defaultCodecs)
        .filter(metricsDTWebClientFilterFunction);
    
    return webClientBuilder.build();
}

【问题讨论】:

    标签: spring-integration webclient spring-webclient


    【解决方案1】:

    webClient 是反应式组件,任​​何反应式流解决方案都需要订阅才能执行。更重要的是,建议以非阻塞方式进行。这就是为什么您在使用 block() 运算符时遇到了这样的 Block Hound 错误。

    由于toEntity() 为我们返回Mono,您只需使用它的subscribe() 来启动请求执行。它可能会立即从您的verifyContract() 中退出,尽管只是因为执行可能发生在不同的线程上。

    这样,您可以考虑将verifyContract() 的合同更改为Mono 以将其传播到下游以便在他们的调用中订阅。

    请了解有关 Project Reactor 的更多信息,以熟悉所有这些阻塞和非阻塞的东西:https://projectreactor.io/

    【讨论】:

    • 我让verifyContract 返回Mono 并且激活器执行suscribe() 就像:lisOperations.verifyEContract(contractRequest, application.getContractData().getRouteOne().getConversationID(), application.getRouteOneId()).subscribe(); 但我的测试正在下降,因为没有执行它(我已经使用wiremock 模拟了外部调用)
    • 正如我所说:反应式在大多数情况下是异步的,因此您的测试可能在没有等待您的请求执行的情况下过早退出。
    • subscribe() 执行需要多长时间?
    • 这取决于其他东西的线程有多忙,让您的请求在WebClient 中执行。正如我所说:您可以将 Mono 一直传播到您在测试中执行的代码。在那里你确实可以打电话给block()。重点是在生产代码中最好避免block()
    猜你喜欢
    • 2021-11-16
    • 2019-04-15
    • 1970-01-01
    • 2013-01-06
    • 1970-01-01
    • 2019-06-21
    • 1970-01-01
    • 2019-12-20
    • 2015-06-30
    相关资源
    最近更新 更多