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

Springboot:如何使用WebClient代替RestTemplate来执行非阻塞和异步调用

常永长
2023-03-14

我有一个springboot项目,它使用springboot RestTemplate。我们已经从1.5.3转移到了SpringBoot2.0.1,并且我们正在尝试通过使用WebClient将rest调用异步化。我们过去使用Resttemplate处理接收到的字符串,如下所示。但是WebClient只返回单点或通量数据。如何将数据作为字符串获取。已经尝试了block()方法,但它执行异步调用。

@Retryable(maxAttempts = 4, value = java.net.ConnectException.class,
           backoff = @Backoff(delay = 3000, multiplier = 2))
public Mono<String> getResponse(String url) {
    return webClient.get().uri(urlForCurrent).accept(APPLICATION_JSON)
                    .retrieve()
                    .bodyToMono(String.class);
}

使用RestTemplate呈现数据流

    null
@RequestMapping(value = traffic/, method = RequestMethod.GET,
                produces = MediaType.APPLICATION_JSON_VALUE)
public String getTraffic(@RequestParam("place") String location) throws InterruptedException, ExecutionException {
    String trafficJSON = Provider.getTrafficJSON(location)
    return trafficJSON;
}
public String getTrafficJSON(String location) {
    String url = ----;

    ResponseEntity<String> response = dataFetcher.getResponse(url);

    /// RESPONSEBODY IS READ AS STRING AND IT NEEDS TO BE PROCESSED
    if (null != response {
        return parser.transformJSON(response.getBody(), params);
    }

    return null;
}
@Retryable(maxAttempts = 4,
           value = java.net.ConnectException.class,
           backoff = @Backoff(delay = 3000, multiplier = 2))
public ResponseEntity<String> getResponse(String url) {
    /* ----------------------- */
    return getRestTemplate().getForEntity(urlForCurrent, String.class);
}

共有1个答案

鲁单弓
2023-03-14

由于有很多误解,所以在这里我要澄清一些事情。

Spring已经正式声明RESTTemplate处于维护模式,所以如果可以的话,可以使用WebClient,如果您想尽可能地成为将来的证明。

如RestTemplate API所述

非反应式应用程序使用Tomcat作为底层服务器实现,这是一个基于servlet的服务器,它将为每个请求分配1个线程,因此您将无法获得与反应式应用程序相比的性能提升。

反应性应用

另一方面,如果您有一个反应性应用程序,那么在任何情况下都不应该在应用程序中调用block()。阻塞正是它所说的,它将阻塞一个线程,阻塞线程的执行,直到它可以继续前进,这在反应世界中是不好的。

我怎么知道我有什么申请?

Spring声明,如果类路径上同时有spring-webspring-webflux,那么应用程序将支持spring-web,并且默认情况下启动一个具有底层tomcat服务器的非反应应用程序。

如果需要,此行为可以作为spring状态手动重写。

@Retryable(maxAttempts = 4,
       value = java.net.ConnectException.class,
       backoff = @Backoff(delay = 3000, multiplier = 2))
public ResponseEntity<String> getResponse(String url) {
    return webClient.get()
            .uri(url)
            .exchange()
            .flatMap(response -> response.toEntity(String.class))
            .block();
}

我想说这是最简单、侵入性最小的实现。当然,您需要在@bean中构建一个合适的webclient,并将其自动转换到它的类中。

 类似资料:
  • 实时的web特性通常需要为每个用户一个大部分时间都处于空闲的长连接. 在传统的同步web服务器中,这意味着需要给每个用户分配一个专用的线程,这样的开销是十分巨大的. 为了减小对于并发连接需要的开销,Tornado使用了一种单线程事件循环的方式. 这意味着所有应用程序代码都应该是异步和非阻塞的,因为在同一时刻只有一个操作是有效的. 异步和非阻塞这两个属于联系十分紧密而且通常交换使用,但是它们并不完全

  • 我认为下面的流量链将通过事件循环放置/执行(像JS)。因此,运行下面的代码将首先打印阻塞循环&然后将执行通量链。 但是,整个通量总是先执行,然后才移动到循环。[我确实有一些语句正在阻塞。但是有两个阶段] 当我们使用reactor时,通过使用一些调度程序来实现异步/非阻塞行为的唯一方法? 如果我不使用任何调度器,并让代码使用当前线程执行,那么即使对于IO密集型应用程序,使用WebFlux而不是Spr

  • 我完全混淆了,,。 哪个是阻塞,哪个不是? 我的意思是如果我使用父进程是否等待子进程返回/才继续执行。 如何影响这些调用?

  • 如另一个问题中所述,当使用Undertow时,所有处理都应该在专用的工作线程池中完成,如下所示: 我知道可用于显式地告诉Undertow在专用的线程池中调度请求以阻止请求。我们可以通过将包装在实例中来修改上面的示例,如下所示: 调用此方法将exchange置于阻塞模式,并创建一个BlockingHttpExchange对象来存储流。当交换处于阻塞模式时,输入流方法变得可用,除了阻塞和非阻塞模式之间

  • 本文向大家介绍java 中同步、异步、阻塞和非阻塞区别详解,包括了java 中同步、异步、阻塞和非阻塞区别详解的使用技巧和注意事项,需要的朋友参考一下 java 中同步、异步、阻塞和非阻塞区别详解 简单点说: 阻塞就是干不完不准回来,一直处于等待中,直到事情处理完成才返回; 非阻塞就是你先干,我先看看有其他事没有,一发现事情被卡住,马上报告领导。 我们拿最常用的send和recv两个函数来说吧..

  • 我搜索了许多网站和文档,但异步调用使用的代码相同。但不确定为什么它不起作用。如果我错过了什么,有人能帮我吗?